@zapier/zapier-sdk 0.78.0 → 0.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/experimental.cjs +1232 -227
- package/dist/experimental.d.mts +2 -2
- package/dist/experimental.d.ts +2 -2
- package/dist/experimental.mjs +1226 -228
- package/dist/{index-BgbftweS.d.mts → index-Dpl8IaV9.d.mts} +647 -62
- package/dist/{index-BgbftweS.d.ts → index-Dpl8IaV9.d.ts} +647 -62
- package/dist/index.cjs +1226 -221
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1220 -222
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -53,18 +53,20 @@ function buildRegistry({
|
|
|
53
53
|
sdk,
|
|
54
54
|
meta,
|
|
55
55
|
formatters,
|
|
56
|
+
boundResolvers,
|
|
57
|
+
positional,
|
|
56
58
|
packageFilter
|
|
57
59
|
}) {
|
|
58
60
|
const definitionsByKey = /* @__PURE__ */ new Map();
|
|
59
61
|
const objectDeclaredKeys = /* @__PURE__ */ new Set();
|
|
60
62
|
for (const m of Object.values(meta)) {
|
|
61
63
|
for (const ref of m.categories ?? []) {
|
|
62
|
-
const
|
|
64
|
+
const key2 = typeof ref === "string" ? ref : ref.key;
|
|
63
65
|
if (typeof ref === "object") {
|
|
64
|
-
objectDeclaredKeys.add(
|
|
65
|
-
definitionsByKey.set(
|
|
66
|
-
} else if (!objectDeclaredKeys.has(
|
|
67
|
-
definitionsByKey.set(
|
|
66
|
+
objectDeclaredKeys.add(key2);
|
|
67
|
+
definitionsByKey.set(key2, resolveCategoryDefinition(ref));
|
|
68
|
+
} else if (!objectDeclaredKeys.has(key2)) {
|
|
69
|
+
definitionsByKey.set(key2, resolveCategoryDefinition(ref));
|
|
68
70
|
}
|
|
69
71
|
}
|
|
70
72
|
}
|
|
@@ -72,16 +74,16 @@ function buildRegistry({
|
|
|
72
74
|
definitionsByKey.set("other", resolveCategoryDefinition("other"));
|
|
73
75
|
}
|
|
74
76
|
const knownCategories = Array.from(definitionsByKey.keys());
|
|
75
|
-
const functions = Object.keys(meta).filter((
|
|
76
|
-
const property = sdk[
|
|
77
|
+
const functions = Object.keys(meta).filter((key2) => {
|
|
78
|
+
const property = sdk[key2];
|
|
77
79
|
if (typeof property === "function") return true;
|
|
78
|
-
const [rootKey] =
|
|
80
|
+
const [rootKey] = key2.split(".");
|
|
79
81
|
const rootProperty = sdk[rootKey];
|
|
80
82
|
return typeof rootProperty === "object" && rootProperty !== null;
|
|
81
|
-
}).map((
|
|
82
|
-
const m = meta[
|
|
83
|
+
}).map((key2) => {
|
|
84
|
+
const m = meta[key2];
|
|
83
85
|
return {
|
|
84
|
-
name:
|
|
86
|
+
name: key2,
|
|
85
87
|
description: m.description,
|
|
86
88
|
type: m.type,
|
|
87
89
|
itemType: m.itemType,
|
|
@@ -89,11 +91,13 @@ function buildRegistry({
|
|
|
89
91
|
inputSchema: canonicalInputSchema(m.inputSchema),
|
|
90
92
|
inputParameters: m.inputParameters,
|
|
91
93
|
outputSchema: m.outputSchema,
|
|
94
|
+
positional: positional?.[key2],
|
|
92
95
|
categories: (m.categories ?? []).map(
|
|
93
96
|
(c) => typeof c === "string" ? c : c.key
|
|
94
97
|
),
|
|
95
98
|
resolvers: m.resolvers,
|
|
96
|
-
|
|
99
|
+
boundResolvers: boundResolvers?.[key2],
|
|
100
|
+
formatter: formatters?.[key2],
|
|
97
101
|
experimental: m.experimental,
|
|
98
102
|
packages: m.packages,
|
|
99
103
|
confirm: m.confirm ?? (m.type === "delete" ? "delete" : void 0),
|
|
@@ -131,8 +135,8 @@ function composeVoid(existing, added) {
|
|
|
131
135
|
}
|
|
132
136
|
function buildHooks(existing, added) {
|
|
133
137
|
const result = {};
|
|
134
|
-
const
|
|
135
|
-
if (
|
|
138
|
+
const start2 = composeVoid(existing.onMethodStart, added.onMethodStart);
|
|
139
|
+
if (start2) result.onMethodStart = start2;
|
|
136
140
|
const end = composeVoid(existing.onMethodEnd, added.onMethodEnd);
|
|
137
141
|
if (end) result.onMethodEnd = end;
|
|
138
142
|
return result;
|
|
@@ -765,11 +769,11 @@ var RESERVED_ROOT_KEYS = /* @__PURE__ */ new Set([
|
|
|
765
769
|
"context",
|
|
766
770
|
"getRegistry"
|
|
767
771
|
]);
|
|
768
|
-
function hasOwn(obj,
|
|
769
|
-
return Object.prototype.hasOwnProperty.call(obj,
|
|
772
|
+
function hasOwn(obj, key2) {
|
|
773
|
+
return Object.prototype.hasOwnProperty.call(obj, key2);
|
|
770
774
|
}
|
|
771
|
-
function setOwn(target,
|
|
772
|
-
Object.defineProperty(target,
|
|
775
|
+
function setOwn(target, key2, value) {
|
|
776
|
+
Object.defineProperty(target, key2, {
|
|
773
777
|
value,
|
|
774
778
|
enumerable: true,
|
|
775
779
|
configurable: true,
|
|
@@ -781,31 +785,31 @@ function checkCollisions(target, source, kind, callerLabel, override) {
|
|
|
781
785
|
checkRootKeyCollisions(target, Object.keys(source), override, callerLabel);
|
|
782
786
|
return;
|
|
783
787
|
}
|
|
784
|
-
for (const
|
|
785
|
-
if (!override && hasOwn(target,
|
|
788
|
+
for (const key2 of Object.keys(source)) {
|
|
789
|
+
if (!override && hasOwn(target, key2)) {
|
|
786
790
|
throw new Error(
|
|
787
|
-
`${callerLabel}: duplicate ${kind} "${
|
|
791
|
+
`${callerLabel}: duplicate ${kind} "${key2}". If the override is intentional, pass { override: true } in the options.`
|
|
788
792
|
);
|
|
789
793
|
}
|
|
790
794
|
}
|
|
791
795
|
}
|
|
792
796
|
function checkRootKeyCollisions(target, keys, override, callerLabel) {
|
|
793
|
-
for (const
|
|
794
|
-
if (RESERVED_ROOT_KEYS.has(
|
|
797
|
+
for (const key2 of keys) {
|
|
798
|
+
if (RESERVED_ROOT_KEYS.has(key2)) {
|
|
795
799
|
throw new Error(
|
|
796
|
-
`${callerLabel}: plugin attempted to register reserved root key "${
|
|
800
|
+
`${callerLabel}: plugin attempted to register reserved root key "${key2}". The SDK uses this key for its own accessor; rename the plugin's method.`
|
|
797
801
|
);
|
|
798
802
|
}
|
|
799
|
-
if (!override && hasOwn(target,
|
|
803
|
+
if (!override && hasOwn(target, key2)) {
|
|
800
804
|
throw new Error(
|
|
801
|
-
`${callerLabel}: duplicate root key "${
|
|
805
|
+
`${callerLabel}: duplicate root key "${key2}". If the override is intentional, pass { override: true } in the options.`
|
|
802
806
|
);
|
|
803
807
|
}
|
|
804
808
|
}
|
|
805
809
|
}
|
|
806
810
|
function applyOwnProperties(target, source) {
|
|
807
|
-
for (const
|
|
808
|
-
setOwn(target,
|
|
811
|
+
for (const key2 of Object.keys(source)) {
|
|
812
|
+
setOwn(target, key2, source[key2]);
|
|
809
813
|
}
|
|
810
814
|
}
|
|
811
815
|
function createPluginAccumulator(initialProperties = {}, initialContext = {}) {
|
|
@@ -1053,8 +1057,8 @@ function normalizeImports(deps) {
|
|
|
1053
1057
|
}
|
|
1054
1058
|
function collectLeafMeta(config) {
|
|
1055
1059
|
let meta;
|
|
1056
|
-
for (const
|
|
1057
|
-
if (config[
|
|
1060
|
+
for (const key2 of LEAF_META_KEYS) {
|
|
1061
|
+
if (config[key2] !== void 0) (meta ?? (meta = {}))[key2] = config[key2];
|
|
1058
1062
|
}
|
|
1059
1063
|
return meta;
|
|
1060
1064
|
}
|
|
@@ -1077,12 +1081,66 @@ function defineMethod(config) {
|
|
|
1077
1081
|
run: config.run
|
|
1078
1082
|
};
|
|
1079
1083
|
}
|
|
1084
|
+
function defineResolver(config) {
|
|
1085
|
+
const deps = normalizeImports(config.imports);
|
|
1086
|
+
const base = { imports: deps.plugins, importBindings: deps.bindings };
|
|
1087
|
+
const gates = {
|
|
1088
|
+
requireParameters: config.requireParameters
|
|
1089
|
+
};
|
|
1090
|
+
switch (config.type) {
|
|
1091
|
+
case "static":
|
|
1092
|
+
return {
|
|
1093
|
+
...base,
|
|
1094
|
+
...gates,
|
|
1095
|
+
type: "static",
|
|
1096
|
+
inputType: config.inputType,
|
|
1097
|
+
placeholder: config.placeholder
|
|
1098
|
+
};
|
|
1099
|
+
case "constant":
|
|
1100
|
+
return { ...base, ...gates, type: "constant", value: config.value };
|
|
1101
|
+
case "info":
|
|
1102
|
+
return { ...base, type: "info", text: config.text ?? "" };
|
|
1103
|
+
case "object":
|
|
1104
|
+
return {
|
|
1105
|
+
...base,
|
|
1106
|
+
...gates,
|
|
1107
|
+
type: "object",
|
|
1108
|
+
properties: config.properties,
|
|
1109
|
+
definitions: config.definitions,
|
|
1110
|
+
getProperties: config.getProperties
|
|
1111
|
+
};
|
|
1112
|
+
case "array":
|
|
1113
|
+
return {
|
|
1114
|
+
...base,
|
|
1115
|
+
...gates,
|
|
1116
|
+
type: "array",
|
|
1117
|
+
items: config.items,
|
|
1118
|
+
minItems: config.minItems,
|
|
1119
|
+
maxItems: config.maxItems,
|
|
1120
|
+
itemValueType: config.itemValueType,
|
|
1121
|
+
definitions: config.definitions
|
|
1122
|
+
};
|
|
1123
|
+
default:
|
|
1124
|
+
return {
|
|
1125
|
+
...base,
|
|
1126
|
+
...gates,
|
|
1127
|
+
type: "dynamic",
|
|
1128
|
+
inputType: config.inputType,
|
|
1129
|
+
placeholder: config.placeholder,
|
|
1130
|
+
getContext: config.getContext,
|
|
1131
|
+
listItems: config.listItems,
|
|
1132
|
+
prompt: config.prompt,
|
|
1133
|
+
tryResolveWithoutPrompt: config.tryResolveWithoutPrompt,
|
|
1134
|
+
tryResolveFromSearch: config.tryResolveFromSearch
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1080
1138
|
function defineFormatter(config) {
|
|
1081
1139
|
const deps = normalizeImports(config.imports);
|
|
1082
1140
|
return {
|
|
1083
1141
|
imports: deps.plugins,
|
|
1084
1142
|
importBindings: deps.bindings,
|
|
1085
|
-
|
|
1143
|
+
getContext: config.getContext,
|
|
1086
1144
|
format: config.format
|
|
1087
1145
|
};
|
|
1088
1146
|
}
|
|
@@ -1211,7 +1269,7 @@ function legacyGraphEntry(name, value, pluginMeta) {
|
|
|
1211
1269
|
function adaptLegacyFormatter(legacy, sdk) {
|
|
1212
1270
|
const legacyFetch = legacy.fetch;
|
|
1213
1271
|
return {
|
|
1214
|
-
|
|
1272
|
+
getContext: legacyFetch ? async ({ items, input, context }) => {
|
|
1215
1273
|
let ctx = context;
|
|
1216
1274
|
for (const item of items) {
|
|
1217
1275
|
ctx = await legacyFetch(sdk, input, item, ctx);
|
|
@@ -1227,6 +1285,14 @@ function normalizeFormatter(entry, sdk) {
|
|
|
1227
1285
|
const legacy = entry.meta?.formatter;
|
|
1228
1286
|
return legacy ? adaptLegacyFormatter(legacy, sdk) : void 0;
|
|
1229
1287
|
}
|
|
1288
|
+
function normalizeBoundResolvers(entry) {
|
|
1289
|
+
if (entry.pluginType !== "method") return void 0;
|
|
1290
|
+
return entry.resolvers;
|
|
1291
|
+
}
|
|
1292
|
+
function methodPositional(entry) {
|
|
1293
|
+
if (entry.pluginType !== "method") return void 0;
|
|
1294
|
+
return entry.positional;
|
|
1295
|
+
}
|
|
1230
1296
|
function pluginEntryMeta(entry) {
|
|
1231
1297
|
if (entry.pluginType === "method" && entry.meta) {
|
|
1232
1298
|
return entry.inputSchema ? { ...entry.meta, inputSchema: entry.inputSchema } : entry.meta;
|
|
@@ -1247,11 +1313,24 @@ function buildSurfaceRegistry(context, packageFilter) {
|
|
|
1247
1313
|
if (m) meta[binding] = m;
|
|
1248
1314
|
}
|
|
1249
1315
|
const formatters = {};
|
|
1316
|
+
const boundResolvers = {};
|
|
1317
|
+
const positional = {};
|
|
1250
1318
|
for (const [binding, entry] of Object.entries(entries)) {
|
|
1251
1319
|
const f = normalizeFormatter(entry, surface);
|
|
1252
1320
|
if (f) formatters[binding] = f;
|
|
1253
|
-
|
|
1254
|
-
|
|
1321
|
+
const r = normalizeBoundResolvers(entry);
|
|
1322
|
+
if (r) boundResolvers[binding] = r;
|
|
1323
|
+
const p = methodPositional(entry);
|
|
1324
|
+
if (p) positional[binding] = p;
|
|
1325
|
+
}
|
|
1326
|
+
return buildRegistry({
|
|
1327
|
+
sdk: surface,
|
|
1328
|
+
meta,
|
|
1329
|
+
formatters,
|
|
1330
|
+
boundResolvers,
|
|
1331
|
+
positional,
|
|
1332
|
+
packageFilter
|
|
1333
|
+
});
|
|
1255
1334
|
}
|
|
1256
1335
|
var dangerousContextPlugin = {
|
|
1257
1336
|
pluginType: "property",
|
|
@@ -1368,15 +1447,15 @@ function collectPlugins(root, materialized = /* @__PURE__ */ new Set()) {
|
|
|
1368
1447
|
}
|
|
1369
1448
|
return byId;
|
|
1370
1449
|
}
|
|
1371
|
-
function bindValue(target,
|
|
1450
|
+
function bindValue(target, key2, entry) {
|
|
1372
1451
|
if (entry.pluginType === "property" && entry.getValue) {
|
|
1373
|
-
Object.defineProperty(target,
|
|
1452
|
+
Object.defineProperty(target, key2, {
|
|
1374
1453
|
get: entry.getValue,
|
|
1375
1454
|
enumerable: true,
|
|
1376
1455
|
configurable: true
|
|
1377
1456
|
});
|
|
1378
1457
|
} else {
|
|
1379
|
-
Object.defineProperty(target,
|
|
1458
|
+
Object.defineProperty(target, key2, {
|
|
1380
1459
|
value: entry.value,
|
|
1381
1460
|
writable: true,
|
|
1382
1461
|
enumerable: true,
|
|
@@ -1428,8 +1507,7 @@ function bindResolver(resolver, plugins) {
|
|
|
1428
1507
|
case "static":
|
|
1429
1508
|
return {
|
|
1430
1509
|
type: "static",
|
|
1431
|
-
|
|
1432
|
-
requireCapabilities: resolver.requireCapabilities,
|
|
1510
|
+
requireParameters: resolver.requireParameters,
|
|
1433
1511
|
inputType: resolver.inputType,
|
|
1434
1512
|
placeholder: resolver.placeholder
|
|
1435
1513
|
};
|
|
@@ -1437,8 +1515,7 @@ function bindResolver(resolver, plugins) {
|
|
|
1437
1515
|
return {
|
|
1438
1516
|
type: "constant",
|
|
1439
1517
|
value: resolver.value,
|
|
1440
|
-
|
|
1441
|
-
requireCapabilities: resolver.requireCapabilities
|
|
1518
|
+
requireParameters: resolver.requireParameters
|
|
1442
1519
|
};
|
|
1443
1520
|
case "info":
|
|
1444
1521
|
return { type: "info", text: resolver.text };
|
|
@@ -1446,24 +1523,24 @@ function bindResolver(resolver, plugins) {
|
|
|
1446
1523
|
const imports = buildImports(plugins, resolver.importBindings);
|
|
1447
1524
|
const bound = {
|
|
1448
1525
|
type: "object",
|
|
1449
|
-
|
|
1450
|
-
requireCapabilities: resolver.requireCapabilities
|
|
1526
|
+
requireParameters: resolver.requireParameters
|
|
1451
1527
|
};
|
|
1452
1528
|
if (resolver.properties)
|
|
1453
1529
|
bound.properties = bindFields(resolver.properties, plugins);
|
|
1454
1530
|
if (resolver.definitions)
|
|
1455
1531
|
bound.definitions = bindDefinitions(resolver.definitions, plugins);
|
|
1456
|
-
const {
|
|
1457
|
-
if (
|
|
1532
|
+
const { getProperties } = resolver;
|
|
1533
|
+
if (getProperties)
|
|
1534
|
+
bound.getProperties = ({ input }) => getProperties({ imports, input });
|
|
1458
1535
|
return bound;
|
|
1459
1536
|
}
|
|
1460
1537
|
case "array": {
|
|
1461
1538
|
const bound = {
|
|
1462
1539
|
type: "array",
|
|
1463
|
-
|
|
1464
|
-
requireCapabilities: resolver.requireCapabilities,
|
|
1540
|
+
requireParameters: resolver.requireParameters,
|
|
1465
1541
|
minItems: resolver.minItems,
|
|
1466
1542
|
maxItems: resolver.maxItems,
|
|
1543
|
+
itemValueType: resolver.itemValueType,
|
|
1467
1544
|
items: isResolverRef(resolver.items) ? resolver.items : bindResolver(resolver.items, plugins)
|
|
1468
1545
|
};
|
|
1469
1546
|
if (resolver.definitions)
|
|
@@ -1474,17 +1551,26 @@ function bindResolver(resolver, plugins) {
|
|
|
1474
1551
|
const imports = buildImports(plugins, resolver.importBindings);
|
|
1475
1552
|
const bound = {
|
|
1476
1553
|
type: "dynamic",
|
|
1477
|
-
|
|
1478
|
-
requireCapabilities: resolver.requireCapabilities,
|
|
1554
|
+
requireParameters: resolver.requireParameters,
|
|
1479
1555
|
inputType: resolver.inputType,
|
|
1480
1556
|
placeholder: resolver.placeholder,
|
|
1481
1557
|
prompt: resolver.prompt
|
|
1482
1558
|
};
|
|
1483
|
-
const {
|
|
1484
|
-
|
|
1485
|
-
|
|
1559
|
+
const {
|
|
1560
|
+
getContext: getContext2,
|
|
1561
|
+
listItems,
|
|
1562
|
+
tryResolveWithoutPrompt,
|
|
1563
|
+
tryResolveFromSearch
|
|
1564
|
+
} = resolver;
|
|
1565
|
+
if (getContext2)
|
|
1566
|
+
bound.getContext = ({ input }) => getContext2({ imports, input });
|
|
1567
|
+
if (listItems)
|
|
1568
|
+
bound.listItems = ({ input, context, search, cursor }) => listItems({ imports, input, context, search, cursor });
|
|
1486
1569
|
if (tryResolveWithoutPrompt) {
|
|
1487
|
-
bound.tryResolveWithoutPrompt = ({
|
|
1570
|
+
bound.tryResolveWithoutPrompt = ({ input }) => tryResolveWithoutPrompt({ imports, input });
|
|
1571
|
+
}
|
|
1572
|
+
if (tryResolveFromSearch) {
|
|
1573
|
+
bound.tryResolveFromSearch = ({ input, search }) => tryResolveFromSearch({ imports, input, search });
|
|
1488
1574
|
}
|
|
1489
1575
|
return bound;
|
|
1490
1576
|
}
|
|
@@ -1492,8 +1578,8 @@ function bindResolver(resolver, plugins) {
|
|
|
1492
1578
|
}
|
|
1493
1579
|
function bindFields(fields, plugins) {
|
|
1494
1580
|
const out = {};
|
|
1495
|
-
for (const [
|
|
1496
|
-
out[
|
|
1581
|
+
for (const [key2, field] of Object.entries(fields)) {
|
|
1582
|
+
out[key2] = {
|
|
1497
1583
|
...field,
|
|
1498
1584
|
resolver: isResolverRef(field.resolver) ? field.resolver : bindResolver(field.resolver, plugins)
|
|
1499
1585
|
};
|
|
@@ -1502,17 +1588,17 @@ function bindFields(fields, plugins) {
|
|
|
1502
1588
|
}
|
|
1503
1589
|
function bindDefinitions(definitions, plugins) {
|
|
1504
1590
|
const out = {};
|
|
1505
|
-
for (const [
|
|
1506
|
-
out[
|
|
1591
|
+
for (const [key2, def] of Object.entries(definitions)) {
|
|
1592
|
+
out[key2] = bindResolver(def, plugins);
|
|
1507
1593
|
}
|
|
1508
1594
|
return out;
|
|
1509
1595
|
}
|
|
1510
1596
|
function bindFormatter(formatter, plugins) {
|
|
1511
1597
|
const imports = buildImports(plugins, formatter.importBindings);
|
|
1512
1598
|
const bound = { format: formatter.format };
|
|
1513
|
-
const {
|
|
1514
|
-
if (
|
|
1515
|
-
bound.
|
|
1599
|
+
const { getContext: getContext2 } = formatter;
|
|
1600
|
+
if (getContext2)
|
|
1601
|
+
bound.getContext = ({ items, input, context }) => getContext2({ imports, items, input, context });
|
|
1516
1602
|
return bound;
|
|
1517
1603
|
}
|
|
1518
1604
|
function bindAttachments(descriptors, context) {
|
|
@@ -1560,6 +1646,7 @@ function runLegacyPass(descriptors, context) {
|
|
|
1560
1646
|
const sdk = this ?? exports;
|
|
1561
1647
|
const meta2 = {};
|
|
1562
1648
|
const formatters = {};
|
|
1649
|
+
const boundResolvers = {};
|
|
1563
1650
|
for (const [binding, id2] of Object.entries(context.surface)) {
|
|
1564
1651
|
const entry = context.plugins[id2];
|
|
1565
1652
|
if (!entry || entry.pluginType === "aggregate") continue;
|
|
@@ -1567,12 +1654,15 @@ function runLegacyPass(descriptors, context) {
|
|
|
1567
1654
|
if (m) meta2[binding] = m;
|
|
1568
1655
|
const f = normalizeFormatter(entry, sdk);
|
|
1569
1656
|
if (f) formatters[binding] = f;
|
|
1657
|
+
const r = normalizeBoundResolvers(entry);
|
|
1658
|
+
if (r) boundResolvers[binding] = r;
|
|
1570
1659
|
}
|
|
1571
1660
|
Object.assign(meta2, context.meta);
|
|
1572
1661
|
return buildRegistry({
|
|
1573
1662
|
sdk,
|
|
1574
1663
|
meta: meta2,
|
|
1575
1664
|
formatters,
|
|
1665
|
+
boundResolvers,
|
|
1576
1666
|
packageFilter: options?.package
|
|
1577
1667
|
});
|
|
1578
1668
|
};
|
|
@@ -1788,7 +1878,7 @@ function createSdk(root) {
|
|
|
1788
1878
|
pluginSurface = {};
|
|
1789
1879
|
bindValue(pluginSurface, plugin.name, plugins2[plugin.id]);
|
|
1790
1880
|
}
|
|
1791
|
-
for (const
|
|
1881
|
+
for (const key2 of Object.keys(legacyExports)) context.surface[key2] = key2;
|
|
1792
1882
|
if (plugin.pluginType === "aggregate") {
|
|
1793
1883
|
recordExportSurface(context, plugin.exports);
|
|
1794
1884
|
} else {
|
|
@@ -1858,6 +1948,756 @@ function addPlugin(sdk, plugin, options) {
|
|
|
1858
1948
|
options ?? {}
|
|
1859
1949
|
);
|
|
1860
1950
|
}
|
|
1951
|
+
var CORE_SIGNAL_SYMBOL = Symbol.for("kitcore.signal");
|
|
1952
|
+
var CoreSignal = class extends Error {
|
|
1953
|
+
constructor(message) {
|
|
1954
|
+
super(message);
|
|
1955
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
1956
|
+
Object.defineProperty(this, CORE_SIGNAL_SYMBOL, {
|
|
1957
|
+
value: true,
|
|
1958
|
+
enumerable: false,
|
|
1959
|
+
configurable: true,
|
|
1960
|
+
writable: false
|
|
1961
|
+
});
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
function isCoreSignal(value) {
|
|
1965
|
+
return Boolean(
|
|
1966
|
+
value && typeof value === "object" && value[CORE_SIGNAL_SYMBOL] === true
|
|
1967
|
+
);
|
|
1968
|
+
}
|
|
1969
|
+
var CoreCancelledSignal = class extends CoreSignal {
|
|
1970
|
+
constructor(message = "resolution cancelled") {
|
|
1971
|
+
super(message);
|
|
1972
|
+
this.name = "CoreCancelledSignal";
|
|
1973
|
+
this.code = "CANCELLED";
|
|
1974
|
+
}
|
|
1975
|
+
};
|
|
1976
|
+
function unwrap(schema) {
|
|
1977
|
+
let inner = schema;
|
|
1978
|
+
let required = true;
|
|
1979
|
+
for (; ; ) {
|
|
1980
|
+
if (inner instanceof zod.z.ZodOptional) {
|
|
1981
|
+
required = false;
|
|
1982
|
+
inner = inner._zod.def.innerType;
|
|
1983
|
+
} else if (inner instanceof zod.z.ZodDefault) {
|
|
1984
|
+
required = false;
|
|
1985
|
+
inner = inner._zod.def.innerType;
|
|
1986
|
+
} else if (inner instanceof zod.z.ZodNullable) {
|
|
1987
|
+
inner = inner._zod.def.innerType;
|
|
1988
|
+
} else {
|
|
1989
|
+
break;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
return { inner, required };
|
|
1993
|
+
}
|
|
1994
|
+
function valueTypeOf(inner) {
|
|
1995
|
+
if (inner instanceof zod.z.ZodString) return "string";
|
|
1996
|
+
if (inner instanceof zod.z.ZodNumber) return "number";
|
|
1997
|
+
if (inner instanceof zod.z.ZodBoolean) return "boolean";
|
|
1998
|
+
if (inner instanceof zod.z.ZodEnum) return "string";
|
|
1999
|
+
if (inner instanceof zod.z.ZodArray) return "array";
|
|
2000
|
+
if (inner instanceof zod.z.ZodObject) return "object";
|
|
2001
|
+
return void 0;
|
|
2002
|
+
}
|
|
2003
|
+
function staticChoicesOf(inner) {
|
|
2004
|
+
if (inner instanceof zod.z.ZodEnum) {
|
|
2005
|
+
const values = inner.options;
|
|
2006
|
+
return values.map((value) => ({ label: value, value }));
|
|
2007
|
+
}
|
|
2008
|
+
return void 0;
|
|
2009
|
+
}
|
|
2010
|
+
function objectShape(schema) {
|
|
2011
|
+
const { inner } = schema ? unwrap(schema) : { inner: void 0 };
|
|
2012
|
+
if (inner instanceof zod.z.ZodObject) {
|
|
2013
|
+
return inner.shape;
|
|
2014
|
+
}
|
|
2015
|
+
return void 0;
|
|
2016
|
+
}
|
|
2017
|
+
function topoOrder2(specs) {
|
|
2018
|
+
const byName = new Map(specs.map((s) => [s.name, s]));
|
|
2019
|
+
const ordered = [];
|
|
2020
|
+
const placed = /* @__PURE__ */ new Set();
|
|
2021
|
+
let progressed = true;
|
|
2022
|
+
while (ordered.length < specs.length && progressed) {
|
|
2023
|
+
progressed = false;
|
|
2024
|
+
for (const spec of specs) {
|
|
2025
|
+
if (placed.has(spec.name)) continue;
|
|
2026
|
+
const ready = spec.requires.every((r) => !byName.has(r) || placed.has(r));
|
|
2027
|
+
if (ready) {
|
|
2028
|
+
ordered.push(spec);
|
|
2029
|
+
placed.add(spec.name);
|
|
2030
|
+
progressed = true;
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
for (const spec of specs) if (!placed.has(spec.name)) ordered.push(spec);
|
|
2035
|
+
return ordered;
|
|
2036
|
+
}
|
|
2037
|
+
function planParameters(entry) {
|
|
2038
|
+
const shape = objectShape(entry.inputSchema);
|
|
2039
|
+
const resolvers = entry.boundResolvers ?? {};
|
|
2040
|
+
const names = shape ? Object.keys(shape) : Object.keys(resolvers);
|
|
2041
|
+
const specs = names.map((name) => {
|
|
2042
|
+
const field = shape?.[name];
|
|
2043
|
+
const { inner, required } = field ? unwrap(field) : { inner: void 0, required: false };
|
|
2044
|
+
const resolver = resolvers[name];
|
|
2045
|
+
return {
|
|
2046
|
+
name,
|
|
2047
|
+
required,
|
|
2048
|
+
valueType: inner ? valueTypeOf(inner) : void 0,
|
|
2049
|
+
staticChoices: inner ? staticChoicesOf(inner) : void 0,
|
|
2050
|
+
resolver,
|
|
2051
|
+
requires: resolver?.requireParameters ?? []
|
|
2052
|
+
};
|
|
2053
|
+
});
|
|
2054
|
+
return { parameters: topoOrder2(specs) };
|
|
2055
|
+
}
|
|
2056
|
+
function getAtPath(root, path) {
|
|
2057
|
+
let node = root;
|
|
2058
|
+
for (const seg of path) {
|
|
2059
|
+
if (node == null || typeof node !== "object") return void 0;
|
|
2060
|
+
node = node[seg];
|
|
2061
|
+
}
|
|
2062
|
+
return node;
|
|
2063
|
+
}
|
|
2064
|
+
function setAtPath(root, path, value) {
|
|
2065
|
+
let node = root;
|
|
2066
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
2067
|
+
const seg = path[i];
|
|
2068
|
+
if (node[seg] == null || typeof node[seg] !== "object") node[seg] = {};
|
|
2069
|
+
node = node[seg];
|
|
2070
|
+
}
|
|
2071
|
+
node[path[path.length - 1]] = value;
|
|
2072
|
+
}
|
|
2073
|
+
var key = (path) => path.join(".");
|
|
2074
|
+
function isSettled(state, path) {
|
|
2075
|
+
return state.settled.includes(key(path));
|
|
2076
|
+
}
|
|
2077
|
+
function settle(state, path) {
|
|
2078
|
+
const k = key(path);
|
|
2079
|
+
if (!state.settled.includes(k)) state.settled.push(k);
|
|
2080
|
+
}
|
|
2081
|
+
function clone(state) {
|
|
2082
|
+
return JSON.parse(JSON.stringify(state));
|
|
2083
|
+
}
|
|
2084
|
+
function coerce(leaf, raw) {
|
|
2085
|
+
if (typeof raw !== "string") return raw;
|
|
2086
|
+
if (leaf.valueType === "number") {
|
|
2087
|
+
const n = Number(raw);
|
|
2088
|
+
return raw.trim() !== "" && !Number.isNaN(n) ? n : raw;
|
|
2089
|
+
}
|
|
2090
|
+
if (leaf.valueType === "boolean") {
|
|
2091
|
+
if (raw === "true") return true;
|
|
2092
|
+
if (raw === "false") return false;
|
|
2093
|
+
}
|
|
2094
|
+
return raw;
|
|
2095
|
+
}
|
|
2096
|
+
async function validationError(leaf, value, state) {
|
|
2097
|
+
const context = await resolveContext(leaf, state.resolved);
|
|
2098
|
+
const config = leaf.resolver?.prompt?.({
|
|
2099
|
+
items: state.listing?.items ?? [],
|
|
2100
|
+
input: mergeInput(state.resolved, leaf.extraInput),
|
|
2101
|
+
context
|
|
2102
|
+
});
|
|
2103
|
+
if (!config?.validate) return null;
|
|
2104
|
+
const verdict = config.validate(value);
|
|
2105
|
+
if (verdict === true) return null;
|
|
2106
|
+
return typeof verdict === "string" ? verdict : `${leaf.name}: invalid value`;
|
|
2107
|
+
}
|
|
2108
|
+
function toChoice(c) {
|
|
2109
|
+
const label = "label" in c ? c.label : c.name;
|
|
2110
|
+
const hint = Array.isArray(c.hint) ? c.hint.join(", ") : c.hint;
|
|
2111
|
+
return { label, value: String(c.value), hint };
|
|
2112
|
+
}
|
|
2113
|
+
function isRef(r) {
|
|
2114
|
+
return typeof r === "object" && r !== null && "ref" in r;
|
|
2115
|
+
}
|
|
2116
|
+
function toLeaf(name, field, definitions) {
|
|
2117
|
+
let resolver;
|
|
2118
|
+
let extraInput;
|
|
2119
|
+
if (isRef(field.resolver)) {
|
|
2120
|
+
resolver = definitions?.[field.resolver.ref];
|
|
2121
|
+
extraInput = field.resolver.input;
|
|
2122
|
+
} else {
|
|
2123
|
+
resolver = field.resolver;
|
|
2124
|
+
}
|
|
2125
|
+
return {
|
|
2126
|
+
name,
|
|
2127
|
+
required: field.required ?? false,
|
|
2128
|
+
resolver,
|
|
2129
|
+
extraInput,
|
|
2130
|
+
// Carry the field's value type so nested answers coerce (number/boolean)
|
|
2131
|
+
// the same way top-level params do. Without this a nested `z.number()`
|
|
2132
|
+
// field's typed answer stays a string and fails final validation.
|
|
2133
|
+
valueType: field.valueType,
|
|
2134
|
+
requires: resolver?.requireParameters ?? []
|
|
2135
|
+
};
|
|
2136
|
+
}
|
|
2137
|
+
async function objectChildren(resolver, input) {
|
|
2138
|
+
if (resolver.properties) {
|
|
2139
|
+
return Object.entries(resolver.properties).map(
|
|
2140
|
+
([name, field]) => toLeaf(name, field, resolver.definitions)
|
|
2141
|
+
);
|
|
2142
|
+
}
|
|
2143
|
+
if (!resolver.getProperties) return [];
|
|
2144
|
+
const fields = await resolver.getProperties({ input });
|
|
2145
|
+
return Object.entries(fields).map(([name, field]) => {
|
|
2146
|
+
if (!isRef(field.resolver) && (field.resolver.imports?.length ?? 0) > 0) {
|
|
2147
|
+
throw new Error(
|
|
2148
|
+
`dynamic object field "${name}" inlines an import-bearing resolver; use { ref } into the object's definitions so its imports bind`
|
|
2149
|
+
);
|
|
2150
|
+
}
|
|
2151
|
+
return toLeaf(name, field, resolver.definitions);
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2154
|
+
function arrayItem(resolver) {
|
|
2155
|
+
const items = resolver.items;
|
|
2156
|
+
const valueType = resolver.itemValueType;
|
|
2157
|
+
if (isRef(items)) {
|
|
2158
|
+
return {
|
|
2159
|
+
name: "",
|
|
2160
|
+
required: true,
|
|
2161
|
+
resolver: resolver.definitions?.[items.ref],
|
|
2162
|
+
extraInput: items.input,
|
|
2163
|
+
valueType,
|
|
2164
|
+
requires: []
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
return {
|
|
2168
|
+
name: "",
|
|
2169
|
+
required: true,
|
|
2170
|
+
resolver: items,
|
|
2171
|
+
valueType,
|
|
2172
|
+
requires: []
|
|
2173
|
+
};
|
|
2174
|
+
}
|
|
2175
|
+
function mergeInput(input, extra) {
|
|
2176
|
+
return extra ? { ...input, ...extra } : input;
|
|
2177
|
+
}
|
|
2178
|
+
async function childrenAt(ctx, path, resolved) {
|
|
2179
|
+
if (path.length === 0) return ctx.parameters;
|
|
2180
|
+
const leaf = await leafAt(ctx, path, resolved);
|
|
2181
|
+
if (!leaf?.resolver || leaf.resolver.type !== "object") return [];
|
|
2182
|
+
return objectChildren(leaf.resolver, mergeInput(resolved, leaf.extraInput));
|
|
2183
|
+
}
|
|
2184
|
+
async function leafAt(ctx, path, resolved) {
|
|
2185
|
+
let children = ctx.parameters;
|
|
2186
|
+
let leaf;
|
|
2187
|
+
for (let i = 0; i < path.length; i++) {
|
|
2188
|
+
const seg = path[i];
|
|
2189
|
+
if (typeof seg === "number") {
|
|
2190
|
+
if (leaf?.resolver?.type !== "array") return void 0;
|
|
2191
|
+
leaf = arrayItem(leaf.resolver);
|
|
2192
|
+
} else {
|
|
2193
|
+
leaf = children.find((c) => c.name === seg);
|
|
2194
|
+
if (!leaf) return void 0;
|
|
2195
|
+
}
|
|
2196
|
+
if (i < path.length - 1 && typeof path[i + 1] === "string") {
|
|
2197
|
+
if (leaf?.resolver?.type !== "object") return void 0;
|
|
2198
|
+
children = await objectChildren(
|
|
2199
|
+
leaf.resolver,
|
|
2200
|
+
mergeInput(resolved, leaf.extraInput)
|
|
2201
|
+
);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
return leaf;
|
|
2205
|
+
}
|
|
2206
|
+
async function arrayInfoAt(ctx, path, resolved) {
|
|
2207
|
+
const leaf = await leafAt(ctx, path, resolved);
|
|
2208
|
+
const resolver = leaf?.resolver;
|
|
2209
|
+
if (resolver?.type !== "array") {
|
|
2210
|
+
throw new Error(`expected an array resolver at "${key(path)}"`);
|
|
2211
|
+
}
|
|
2212
|
+
return {
|
|
2213
|
+
min: resolver.minItems ?? 0,
|
|
2214
|
+
max: resolver.maxItems ?? Infinity,
|
|
2215
|
+
item: { ...arrayItem(resolver), name: String(path[path.length - 1]) }
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
2218
|
+
var AFFORDANCE = {
|
|
2219
|
+
choose: { action: "choose", description: "Pick one of the listed options" },
|
|
2220
|
+
custom: {
|
|
2221
|
+
action: "custom",
|
|
2222
|
+
description: "Provide a value directly",
|
|
2223
|
+
supply: "value"
|
|
2224
|
+
},
|
|
2225
|
+
search: {
|
|
2226
|
+
action: "search",
|
|
2227
|
+
description: "Filter the options by a search term",
|
|
2228
|
+
supply: "term"
|
|
2229
|
+
},
|
|
2230
|
+
more: { action: "more", description: "Load more options" },
|
|
2231
|
+
skip: { action: "skip", description: "Omit this optional parameter" },
|
|
2232
|
+
add: { action: "add", description: "Add another item" },
|
|
2233
|
+
done: { action: "done", description: "Finish the list" },
|
|
2234
|
+
retry: { action: "retry", description: "Retry loading the options" },
|
|
2235
|
+
cancel: { action: "cancel", description: "Cancel resolution" }
|
|
2236
|
+
};
|
|
2237
|
+
async function firstPage(result) {
|
|
2238
|
+
const page = await result;
|
|
2239
|
+
return {
|
|
2240
|
+
data: Array.isArray(page?.data) ? page.data : [],
|
|
2241
|
+
nextCursor: page?.nextCursor
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
async function resolveContext(leaf, input) {
|
|
2245
|
+
return leaf.resolver?.getContext?.({
|
|
2246
|
+
input: mergeInput(input, leaf.extraInput)
|
|
2247
|
+
});
|
|
2248
|
+
}
|
|
2249
|
+
async function fetchListing(leaf, input, opts = {}) {
|
|
2250
|
+
const page = await firstPage(
|
|
2251
|
+
leaf.resolver?.listItems?.({
|
|
2252
|
+
input: mergeInput(input, leaf.extraInput),
|
|
2253
|
+
context: opts.context,
|
|
2254
|
+
search: opts.search,
|
|
2255
|
+
cursor: opts.cursor
|
|
2256
|
+
})
|
|
2257
|
+
);
|
|
2258
|
+
return {
|
|
2259
|
+
items: [...opts.priorItems ?? [], ...page.data],
|
|
2260
|
+
cursor: page.nextCursor,
|
|
2261
|
+
search: opts.search,
|
|
2262
|
+
exhausted: page.nextCursor == null
|
|
2263
|
+
};
|
|
2264
|
+
}
|
|
2265
|
+
function selectActions(leaf, listing, multiple) {
|
|
2266
|
+
const actions = multiple ? [AFFORDANCE.choose] : [AFFORDANCE.choose, AFFORDANCE.custom];
|
|
2267
|
+
if (leaf.resolver?.inputType === "search") actions.push(AFFORDANCE.search);
|
|
2268
|
+
if (listing.cursor) actions.push(AFFORDANCE.more);
|
|
2269
|
+
if (!leaf.required) actions.push(AFFORDANCE.skip);
|
|
2270
|
+
return actions;
|
|
2271
|
+
}
|
|
2272
|
+
function selectQuestion(leaf, input, listing, context) {
|
|
2273
|
+
const config = leaf.resolver?.prompt?.({
|
|
2274
|
+
items: listing.items,
|
|
2275
|
+
input: mergeInput(input, leaf.extraInput),
|
|
2276
|
+
context
|
|
2277
|
+
});
|
|
2278
|
+
const multiple = config?.type === "checkbox";
|
|
2279
|
+
return {
|
|
2280
|
+
type: "select",
|
|
2281
|
+
message: config?.message ?? `Select ${leaf.name}:`,
|
|
2282
|
+
choices: (config?.choices ?? []).map(toChoice),
|
|
2283
|
+
...multiple ? { multiple: true } : {},
|
|
2284
|
+
...config?.notes?.length ? { notes: config.notes } : {},
|
|
2285
|
+
actions: selectActions(leaf, listing, multiple)
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
function toControllerError(error) {
|
|
2289
|
+
if (error instanceof Error) {
|
|
2290
|
+
const code = error.code;
|
|
2291
|
+
return {
|
|
2292
|
+
name: error.name,
|
|
2293
|
+
message: error.message,
|
|
2294
|
+
...typeof code === "string" ? { code } : {}
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
return { name: "Error", message: String(error) };
|
|
2298
|
+
}
|
|
2299
|
+
function failedResult(state, name, error) {
|
|
2300
|
+
return {
|
|
2301
|
+
state,
|
|
2302
|
+
result: {
|
|
2303
|
+
status: "failed",
|
|
2304
|
+
error: toControllerError(error),
|
|
2305
|
+
question: {
|
|
2306
|
+
type: "select",
|
|
2307
|
+
message: `Could not load options for ${name}.`,
|
|
2308
|
+
choices: [],
|
|
2309
|
+
actions: [AFFORDANCE.retry, AFFORDANCE.cancel]
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
async function buildQuestion(leaf, input) {
|
|
2315
|
+
const optional = !leaf.required;
|
|
2316
|
+
const resolver = leaf.resolver;
|
|
2317
|
+
if (resolver?.listItems) {
|
|
2318
|
+
const context = await resolveContext(leaf, input);
|
|
2319
|
+
const listing = await fetchListing(leaf, input, { context });
|
|
2320
|
+
return {
|
|
2321
|
+
question: selectQuestion(leaf, input, listing, context),
|
|
2322
|
+
listing
|
|
2323
|
+
};
|
|
2324
|
+
}
|
|
2325
|
+
if (leaf.staticChoices) {
|
|
2326
|
+
const actions2 = [AFFORDANCE.choose];
|
|
2327
|
+
if (optional) actions2.push(AFFORDANCE.skip);
|
|
2328
|
+
return {
|
|
2329
|
+
question: {
|
|
2330
|
+
type: "select",
|
|
2331
|
+
message: `Select ${leaf.name}:`,
|
|
2332
|
+
choices: leaf.staticChoices,
|
|
2333
|
+
actions: actions2
|
|
2334
|
+
}
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2337
|
+
const inputType = resolver?.inputType && resolver.inputType !== "search" ? resolver.inputType : "text";
|
|
2338
|
+
const actions = [AFFORDANCE.custom];
|
|
2339
|
+
if (optional) actions.push(AFFORDANCE.skip);
|
|
2340
|
+
return {
|
|
2341
|
+
question: {
|
|
2342
|
+
type: "input",
|
|
2343
|
+
message: `Enter ${leaf.name}:`,
|
|
2344
|
+
inputType,
|
|
2345
|
+
placeholder: resolver?.placeholder,
|
|
2346
|
+
actions
|
|
2347
|
+
}
|
|
2348
|
+
};
|
|
2349
|
+
}
|
|
2350
|
+
function finalize(ctx, resolved) {
|
|
2351
|
+
if (!ctx.schema) return { status: "done", value: resolved };
|
|
2352
|
+
const parsed = ctx.schema.safeParse(resolved);
|
|
2353
|
+
if (parsed.success) {
|
|
2354
|
+
return { status: "done", value: parsed.data };
|
|
2355
|
+
}
|
|
2356
|
+
const issues = parsed.error.issues.map((i) => ({
|
|
2357
|
+
parameter: i.path.map(String).join(".") || void 0,
|
|
2358
|
+
message: i.message
|
|
2359
|
+
}));
|
|
2360
|
+
return { status: "invalid", issues };
|
|
2361
|
+
}
|
|
2362
|
+
function collectionQuestion(t) {
|
|
2363
|
+
const actions = [AFFORDANCE.add];
|
|
2364
|
+
if (t.count >= t.min) actions.push(AFFORDANCE.done);
|
|
2365
|
+
return {
|
|
2366
|
+
type: "collection",
|
|
2367
|
+
message: `Add another ${t.path[t.path.length - 1]}? (${t.count} so far)`,
|
|
2368
|
+
count: t.count,
|
|
2369
|
+
min: t.min,
|
|
2370
|
+
// An unbounded array's max is Infinity, which JSON.stringify turns to null;
|
|
2371
|
+
// omit it so the question round-trips across the wall as plain data.
|
|
2372
|
+
...Number.isFinite(t.max) ? { max: t.max } : {},
|
|
2373
|
+
actions
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
async function findInArray(ctx, state, path) {
|
|
2377
|
+
if (isSettled(state, path)) return null;
|
|
2378
|
+
if (getAtPath(state.resolved, path) == null)
|
|
2379
|
+
setAtPath(state.resolved, path, []);
|
|
2380
|
+
if (!state.interactive) {
|
|
2381
|
+
settle(state, path);
|
|
2382
|
+
return null;
|
|
2383
|
+
}
|
|
2384
|
+
const { min, max, item } = await arrayInfoAt(ctx, path, state.resolved);
|
|
2385
|
+
const items = getAtPath(state.resolved, path);
|
|
2386
|
+
const len = items.length;
|
|
2387
|
+
const itemType = item.resolver?.type;
|
|
2388
|
+
if (len > 0 && (itemType === "object" || itemType === "array")) {
|
|
2389
|
+
const inner = await findNext(ctx, state, [...path, len - 1]);
|
|
2390
|
+
if (inner) return inner;
|
|
2391
|
+
}
|
|
2392
|
+
if (len < min) return descendItem(ctx, state, path, len, item);
|
|
2393
|
+
if (len < max) return { kind: "array", path, count: len, min, max };
|
|
2394
|
+
settle(state, path);
|
|
2395
|
+
return null;
|
|
2396
|
+
}
|
|
2397
|
+
function seedItemSlot(state, itemPath, item) {
|
|
2398
|
+
const type = item.resolver?.type;
|
|
2399
|
+
if (type === "object") {
|
|
2400
|
+
setAtPath(state.resolved, itemPath, {});
|
|
2401
|
+
return "object";
|
|
2402
|
+
}
|
|
2403
|
+
if (type === "array") {
|
|
2404
|
+
setAtPath(state.resolved, itemPath, []);
|
|
2405
|
+
return "array";
|
|
2406
|
+
}
|
|
2407
|
+
return "leaf";
|
|
2408
|
+
}
|
|
2409
|
+
async function descendItem(ctx, state, arrayPath, index, item) {
|
|
2410
|
+
const itemPath = [...arrayPath, index];
|
|
2411
|
+
const kind = seedItemSlot(state, itemPath, item);
|
|
2412
|
+
if (kind === "object") return findNext(ctx, state, itemPath);
|
|
2413
|
+
if (kind === "array") return findInArray(ctx, state, itemPath);
|
|
2414
|
+
return { kind: "leaf", path: itemPath, leaf: item };
|
|
2415
|
+
}
|
|
2416
|
+
async function findNext(ctx, state, path = []) {
|
|
2417
|
+
const container = getAtPath(state.resolved, path) ?? {};
|
|
2418
|
+
for (const leaf of await childrenAt(ctx, path, state.resolved)) {
|
|
2419
|
+
const childPath = [...path, leaf.name];
|
|
2420
|
+
if (!leaf.requires.every((r) => container[r] !== void 0)) continue;
|
|
2421
|
+
if (leaf.resolver?.type === "object") {
|
|
2422
|
+
if (getAtPath(state.resolved, childPath) == null)
|
|
2423
|
+
setAtPath(state.resolved, childPath, {});
|
|
2424
|
+
const inner = await findNext(ctx, state, childPath);
|
|
2425
|
+
if (inner) return inner;
|
|
2426
|
+
continue;
|
|
2427
|
+
}
|
|
2428
|
+
if (leaf.resolver?.type === "array") {
|
|
2429
|
+
const inner = await findInArray(ctx, state, childPath);
|
|
2430
|
+
if (inner) return inner;
|
|
2431
|
+
continue;
|
|
2432
|
+
}
|
|
2433
|
+
if (container[leaf.name] !== void 0 || isSettled(state, childPath))
|
|
2434
|
+
continue;
|
|
2435
|
+
return { kind: "leaf", path: childPath, leaf };
|
|
2436
|
+
}
|
|
2437
|
+
return null;
|
|
2438
|
+
}
|
|
2439
|
+
async function askLeaf(state, path, leaf, opts = {}) {
|
|
2440
|
+
state.current = path;
|
|
2441
|
+
try {
|
|
2442
|
+
const { question, listing } = await buildQuestion(leaf, state.resolved);
|
|
2443
|
+
state.listing = listing;
|
|
2444
|
+
return {
|
|
2445
|
+
state,
|
|
2446
|
+
result: {
|
|
2447
|
+
status: "ask",
|
|
2448
|
+
question,
|
|
2449
|
+
...opts.error ? { error: opts.error } : {}
|
|
2450
|
+
}
|
|
2451
|
+
};
|
|
2452
|
+
} catch (error) {
|
|
2453
|
+
state.listing = { items: [], exhausted: false };
|
|
2454
|
+
return failedResult(state, leaf.name, error);
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
async function advance(ctx, state) {
|
|
2458
|
+
for (; ; ) {
|
|
2459
|
+
const target = await findNext(ctx, state);
|
|
2460
|
+
if (!target) {
|
|
2461
|
+
delete state.current;
|
|
2462
|
+
delete state.listing;
|
|
2463
|
+
return { state, result: finalize(ctx, state.resolved) };
|
|
2464
|
+
}
|
|
2465
|
+
if (target.kind === "array") {
|
|
2466
|
+
state.current = target.path;
|
|
2467
|
+
delete state.listing;
|
|
2468
|
+
return {
|
|
2469
|
+
state,
|
|
2470
|
+
result: { status: "ask", question: collectionQuestion(target) }
|
|
2471
|
+
};
|
|
2472
|
+
}
|
|
2473
|
+
const { path, leaf } = target;
|
|
2474
|
+
const auto = await leaf.resolver?.tryResolveWithoutPrompt?.({
|
|
2475
|
+
input: mergeInput(state.resolved, leaf.extraInput)
|
|
2476
|
+
});
|
|
2477
|
+
if (auto) {
|
|
2478
|
+
if (auto.resolvedValue !== void 0)
|
|
2479
|
+
setAtPath(state.resolved, path, auto.resolvedValue);
|
|
2480
|
+
settle(state, path);
|
|
2481
|
+
continue;
|
|
2482
|
+
}
|
|
2483
|
+
if (!state.interactive) {
|
|
2484
|
+
if (!leaf.required) {
|
|
2485
|
+
settle(state, path);
|
|
2486
|
+
continue;
|
|
2487
|
+
}
|
|
2488
|
+
} else if (!leaf.required && !leaf.resolver) {
|
|
2489
|
+
settle(state, path);
|
|
2490
|
+
continue;
|
|
2491
|
+
}
|
|
2492
|
+
return askLeaf(state, path, leaf);
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
async function start(ctx, input = {}, interactive = true) {
|
|
2496
|
+
const resolved = {};
|
|
2497
|
+
for (const spec of ctx.parameters) {
|
|
2498
|
+
if (spec.resolver?.type === "constant")
|
|
2499
|
+
resolved[spec.name] = spec.resolver.value;
|
|
2500
|
+
}
|
|
2501
|
+
Object.assign(resolved, input);
|
|
2502
|
+
return advance(ctx, {
|
|
2503
|
+
method: ctx.method,
|
|
2504
|
+
resolved,
|
|
2505
|
+
settled: [],
|
|
2506
|
+
interactive
|
|
2507
|
+
});
|
|
2508
|
+
}
|
|
2509
|
+
async function step(ctx, prior, action) {
|
|
2510
|
+
const state = clone(prior);
|
|
2511
|
+
if (action.type === "cancel") {
|
|
2512
|
+
delete state.current;
|
|
2513
|
+
delete state.listing;
|
|
2514
|
+
return { state, result: { status: "cancelled" } };
|
|
2515
|
+
}
|
|
2516
|
+
const path = state.current;
|
|
2517
|
+
if (!path) throw new Error("step called with no outstanding question");
|
|
2518
|
+
const leaf = await leafAt(ctx, path, state.resolved);
|
|
2519
|
+
if (leaf && (action.type === "search" || action.type === "more" || action.type === "retry")) {
|
|
2520
|
+
return refine(ctx, state, leaf, path, action);
|
|
2521
|
+
}
|
|
2522
|
+
if (action.type === "add" || action.type === "done") {
|
|
2523
|
+
delete state.current;
|
|
2524
|
+
delete state.listing;
|
|
2525
|
+
if (action.type === "done") {
|
|
2526
|
+
settle(state, path);
|
|
2527
|
+
return advance(ctx, state);
|
|
2528
|
+
}
|
|
2529
|
+
const items = getAtPath(state.resolved, path) ?? [];
|
|
2530
|
+
const { item } = await arrayInfoAt(ctx, path, state.resolved);
|
|
2531
|
+
const itemPath = [...path, items.length];
|
|
2532
|
+
if (seedItemSlot(state, itemPath, item) === "leaf")
|
|
2533
|
+
return askLeaf(state, itemPath, item);
|
|
2534
|
+
return advance(ctx, state);
|
|
2535
|
+
}
|
|
2536
|
+
switch (action.type) {
|
|
2537
|
+
case "choose":
|
|
2538
|
+
case "custom": {
|
|
2539
|
+
if (leaf) {
|
|
2540
|
+
const error = await validationError(leaf, action.value, state);
|
|
2541
|
+
if (error) return askLeaf(state, path, leaf, { error });
|
|
2542
|
+
}
|
|
2543
|
+
setAtPath(
|
|
2544
|
+
state.resolved,
|
|
2545
|
+
path,
|
|
2546
|
+
leaf ? coerce(leaf, action.value) : action.value
|
|
2547
|
+
);
|
|
2548
|
+
break;
|
|
2549
|
+
}
|
|
2550
|
+
case "skip":
|
|
2551
|
+
settle(state, path);
|
|
2552
|
+
break;
|
|
2553
|
+
default:
|
|
2554
|
+
throw new Error(`action "${action.type}" is not supported here`);
|
|
2555
|
+
}
|
|
2556
|
+
delete state.current;
|
|
2557
|
+
delete state.listing;
|
|
2558
|
+
return advance(ctx, state);
|
|
2559
|
+
}
|
|
2560
|
+
async function refine(ctx, state, leaf, path, action) {
|
|
2561
|
+
const attempt = action.type === "search" ? { search: action.term, cursor: void 0, priorItems: [] } : {
|
|
2562
|
+
search: state.listing?.search,
|
|
2563
|
+
cursor: state.listing?.cursor,
|
|
2564
|
+
priorItems: state.listing?.items ?? []
|
|
2565
|
+
};
|
|
2566
|
+
try {
|
|
2567
|
+
if (action.type === "search") {
|
|
2568
|
+
const exact = await leaf.resolver?.tryResolveFromSearch?.({
|
|
2569
|
+
input: mergeInput(state.resolved, leaf.extraInput),
|
|
2570
|
+
search: action.term
|
|
2571
|
+
});
|
|
2572
|
+
if (exact) {
|
|
2573
|
+
setAtPath(state.resolved, path, coerce(leaf, exact.resolvedValue));
|
|
2574
|
+
delete state.current;
|
|
2575
|
+
delete state.listing;
|
|
2576
|
+
return advance(ctx, state);
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
const context = await resolveContext(leaf, state.resolved);
|
|
2580
|
+
state.listing = await fetchListing(leaf, state.resolved, {
|
|
2581
|
+
...attempt,
|
|
2582
|
+
context
|
|
2583
|
+
});
|
|
2584
|
+
return {
|
|
2585
|
+
state,
|
|
2586
|
+
result: {
|
|
2587
|
+
status: "ask",
|
|
2588
|
+
question: selectQuestion(leaf, state.resolved, state.listing, context)
|
|
2589
|
+
}
|
|
2590
|
+
};
|
|
2591
|
+
} catch (error) {
|
|
2592
|
+
state.listing = {
|
|
2593
|
+
items: attempt.priorItems,
|
|
2594
|
+
search: attempt.search,
|
|
2595
|
+
cursor: attempt.cursor,
|
|
2596
|
+
exhausted: false
|
|
2597
|
+
};
|
|
2598
|
+
return failedResult(state, leaf.name, error);
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
function toJsonSchema(schema) {
|
|
2602
|
+
if (!schema) return void 0;
|
|
2603
|
+
try {
|
|
2604
|
+
return zod.z.toJSONSchema(schema);
|
|
2605
|
+
} catch {
|
|
2606
|
+
return void 0;
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
function projectSummary(entry) {
|
|
2610
|
+
return {
|
|
2611
|
+
name: entry.name,
|
|
2612
|
+
...entry.description ? { description: entry.description } : {},
|
|
2613
|
+
...entry.categories?.length ? { categories: entry.categories } : {}
|
|
2614
|
+
};
|
|
2615
|
+
}
|
|
2616
|
+
function projectMethod(entry) {
|
|
2617
|
+
const inputProperties = toJsonSchema(entry.inputSchema)?.properties;
|
|
2618
|
+
const parameters = {};
|
|
2619
|
+
for (const spec of planParameters(entry).parameters) {
|
|
2620
|
+
parameters[spec.name] = {
|
|
2621
|
+
required: spec.required,
|
|
2622
|
+
dynamic: Boolean(spec.resolver?.listItems),
|
|
2623
|
+
...spec.resolver?.inputType === "search" ? { searchable: true } : {},
|
|
2624
|
+
...inputProperties?.[spec.name] ? { schema: inputProperties[spec.name] } : {},
|
|
2625
|
+
...spec.staticChoices ? { choices: spec.staticChoices } : {},
|
|
2626
|
+
...spec.requires.length ? { requireParameters: spec.requires } : {}
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
const output = toJsonSchema(entry.outputSchema);
|
|
2630
|
+
return {
|
|
2631
|
+
name: entry.name,
|
|
2632
|
+
...entry.description ? { description: entry.description } : {},
|
|
2633
|
+
...entry.categories?.length ? { categories: entry.categories } : {},
|
|
2634
|
+
parameters,
|
|
2635
|
+
...entry.positional?.length ? { positional: entry.positional } : {},
|
|
2636
|
+
...output ? { output } : {}
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
function createController(sdk) {
|
|
2640
|
+
function entryFor(method) {
|
|
2641
|
+
const entry = sdk.getRegistry().functions.find((f) => f.name === method);
|
|
2642
|
+
if (!entry) throw new Error(`unknown method "${method}"`);
|
|
2643
|
+
return entry;
|
|
2644
|
+
}
|
|
2645
|
+
function contextFor(method) {
|
|
2646
|
+
const entry = entryFor(method);
|
|
2647
|
+
return {
|
|
2648
|
+
method,
|
|
2649
|
+
schema: entry.inputSchema,
|
|
2650
|
+
parameters: planParameters(entry).parameters
|
|
2651
|
+
};
|
|
2652
|
+
}
|
|
2653
|
+
const start2 = ({ method, input, interactive }) => start(contextFor(method), input, interactive);
|
|
2654
|
+
const step2 = ({ state, action }) => step(contextFor(state.method), state, action);
|
|
2655
|
+
const resolve2 = async ({
|
|
2656
|
+
method,
|
|
2657
|
+
input,
|
|
2658
|
+
answer,
|
|
2659
|
+
interactive
|
|
2660
|
+
}) => {
|
|
2661
|
+
const ctx = contextFor(method);
|
|
2662
|
+
let { state, result } = await start(ctx, input, interactive);
|
|
2663
|
+
while (result.status === "ask" || result.status === "failed") {
|
|
2664
|
+
const action = await answer({ state, result });
|
|
2665
|
+
({ state, result } = await step(ctx, state, action));
|
|
2666
|
+
}
|
|
2667
|
+
if (result.status === "done") return result.value;
|
|
2668
|
+
if (result.status === "cancelled") {
|
|
2669
|
+
throw new CoreCancelledSignal(`resolution cancelled for "${method}"`);
|
|
2670
|
+
}
|
|
2671
|
+
const detail = result.issues.map((i) => i.parameter ? `${i.parameter}: ${i.message}` : i.message).join("; ");
|
|
2672
|
+
throw new Error(`invalid input for "${method}": ${detail}`);
|
|
2673
|
+
};
|
|
2674
|
+
const listMethods = () => ({
|
|
2675
|
+
data: sdk.getRegistry().functions.map(projectSummary)
|
|
2676
|
+
});
|
|
2677
|
+
const getMethod = ({ method }) => ({
|
|
2678
|
+
data: projectMethod(entryFor(method))
|
|
2679
|
+
});
|
|
2680
|
+
const listChoices = async ({
|
|
2681
|
+
method,
|
|
2682
|
+
parameter,
|
|
2683
|
+
input = {},
|
|
2684
|
+
search,
|
|
2685
|
+
cursor
|
|
2686
|
+
}) => {
|
|
2687
|
+
const spec = contextFor(method).parameters.find(
|
|
2688
|
+
(p) => p.name === parameter
|
|
2689
|
+
);
|
|
2690
|
+
if (!spec?.resolver?.listItems) return { data: [] };
|
|
2691
|
+
const context = await spec.resolver.getContext?.({ input });
|
|
2692
|
+
const page = await firstPage(
|
|
2693
|
+
spec.resolver.listItems({ input, context, search, cursor })
|
|
2694
|
+
);
|
|
2695
|
+
const config = spec.resolver.prompt?.({ items: page.data, input, context });
|
|
2696
|
+
const data = (config?.choices ?? []).map(toChoice);
|
|
2697
|
+
return { data, nextCursor: page.nextCursor };
|
|
2698
|
+
};
|
|
2699
|
+
return { resolve: resolve2, start: start2, step: step2, listMethods, getMethod, listChoices };
|
|
2700
|
+
}
|
|
1861
2701
|
function createCorePlugin(options) {
|
|
1862
2702
|
return () => ({
|
|
1863
2703
|
context: {
|
|
@@ -2810,8 +3650,8 @@ function normalizeHeaders(optionsHeaders) {
|
|
|
2810
3650
|
return headers;
|
|
2811
3651
|
}
|
|
2812
3652
|
const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
|
|
2813
|
-
for (const [
|
|
2814
|
-
headers[
|
|
3653
|
+
for (const [key2, value] of headerEntries) {
|
|
3654
|
+
headers[key2] = value;
|
|
2815
3655
|
}
|
|
2816
3656
|
return headers;
|
|
2817
3657
|
}
|
|
@@ -3085,7 +3925,7 @@ var listAppsPlugin = definePlugin(
|
|
|
3085
3925
|
locator
|
|
3086
3926
|
];
|
|
3087
3927
|
}
|
|
3088
|
-
const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator).filter((
|
|
3928
|
+
const duplicatedLookupAppKeys = Object.keys(implementationNameToLocator).filter((key2) => implementationNameToLocator[key2].length > 1).map((key2) => implementationNameToLocator[key2]).flat().map((locator) => locator.lookupAppKey);
|
|
3089
3929
|
if (duplicatedLookupAppKeys.length > 0) {
|
|
3090
3930
|
throw new Error(
|
|
3091
3931
|
`Duplicate lookup app keys found: ${duplicatedLookupAppKeys.join(", ")}`
|
|
@@ -3928,7 +4768,7 @@ function formatRecordError(fieldId, err) {
|
|
|
3928
4768
|
function formatResponseError(err) {
|
|
3929
4769
|
const message = err.human_title || err.title || "Unknown error";
|
|
3930
4770
|
if (err.meta && Object.keys(err.meta).length > 0) {
|
|
3931
|
-
const metaParts = Object.entries(err.meta).map(([
|
|
4771
|
+
const metaParts = Object.entries(err.meta).map(([key2, val]) => `${key2}: ${JSON.stringify(val)}`).join(", ");
|
|
3932
4772
|
return `${message} (${metaParts})`;
|
|
3933
4773
|
}
|
|
3934
4774
|
return message;
|
|
@@ -3963,8 +4803,8 @@ var TrashSchema = zod.z.enum(["exclude", "include", "only"]).optional().describe
|
|
|
3963
4803
|
'Control soft-deleted item visibility. "exclude" (default) returns active items only, "include" returns both active and soft-deleted, "only" returns soft-deleted items only.'
|
|
3964
4804
|
);
|
|
3965
4805
|
var FIELD_ID_PATTERN = /^f\d+$/;
|
|
3966
|
-
function isFieldId(
|
|
3967
|
-
return FIELD_ID_PATTERN.test(
|
|
4806
|
+
function isFieldId(key2) {
|
|
4807
|
+
return FIELD_ID_PATTERN.test(key2);
|
|
3968
4808
|
}
|
|
3969
4809
|
var NESTED_COMPONENTS = {
|
|
3970
4810
|
labeled_string: /* @__PURE__ */ new Set(["value"]),
|
|
@@ -4002,7 +4842,7 @@ async function resolveFieldKeys({
|
|
|
4002
4842
|
fieldKeys
|
|
4003
4843
|
}) {
|
|
4004
4844
|
const allAreIds = fieldKeys.every(
|
|
4005
|
-
(
|
|
4845
|
+
(key2) => typeof key2 === "number" || /^(f?\d+)$/.test(key2)
|
|
4006
4846
|
);
|
|
4007
4847
|
if (allAreIds) {
|
|
4008
4848
|
return fieldKeys.map(toNumericFieldId);
|
|
@@ -4011,13 +4851,13 @@ async function resolveFieldKeys({
|
|
|
4011
4851
|
if (!mapping) {
|
|
4012
4852
|
return fieldKeys.map(toNumericFieldId);
|
|
4013
4853
|
}
|
|
4014
|
-
return fieldKeys.map((
|
|
4015
|
-
if (typeof
|
|
4016
|
-
if (FIELD_ID_PATTERN.test(
|
|
4017
|
-
const id = mapping.nameToId.get(
|
|
4854
|
+
return fieldKeys.map((key2) => {
|
|
4855
|
+
if (typeof key2 === "number") return key2;
|
|
4856
|
+
if (FIELD_ID_PATTERN.test(key2)) return toNumericFieldId(key2);
|
|
4857
|
+
const id = mapping.nameToId.get(key2);
|
|
4018
4858
|
if (!id) {
|
|
4019
4859
|
throw new ZapierValidationError(
|
|
4020
|
-
`Unknown field name: "${
|
|
4860
|
+
`Unknown field name: "${key2}". Use a valid field name or ID.`
|
|
4021
4861
|
);
|
|
4022
4862
|
}
|
|
4023
4863
|
return toNumericFieldId(id);
|
|
@@ -4033,13 +4873,13 @@ async function createFieldKeyTranslator({
|
|
|
4033
4873
|
translateInput(data) {
|
|
4034
4874
|
if (!mapping) return data;
|
|
4035
4875
|
const result = {};
|
|
4036
|
-
for (const [
|
|
4037
|
-
if (FIELD_ID_PATTERN.test(
|
|
4038
|
-
result[
|
|
4039
|
-
} else if (mapping.nameToId.has(
|
|
4040
|
-
result[mapping.nameToId.get(
|
|
4876
|
+
for (const [key2, value] of Object.entries(data)) {
|
|
4877
|
+
if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
|
|
4878
|
+
result[key2] = value;
|
|
4879
|
+
} else if (mapping.nameToId.has(key2)) {
|
|
4880
|
+
result[mapping.nameToId.get(key2)] = value;
|
|
4041
4881
|
} else {
|
|
4042
|
-
result[
|
|
4882
|
+
result[key2] = value;
|
|
4043
4883
|
}
|
|
4044
4884
|
}
|
|
4045
4885
|
return result;
|
|
@@ -4047,29 +4887,29 @@ async function createFieldKeyTranslator({
|
|
|
4047
4887
|
translateOutput(data) {
|
|
4048
4888
|
if (!mapping) return data;
|
|
4049
4889
|
const result = {};
|
|
4050
|
-
for (const [
|
|
4051
|
-
if (mapping.idToName.has(
|
|
4052
|
-
result[mapping.idToName.get(
|
|
4890
|
+
for (const [key2, value] of Object.entries(data)) {
|
|
4891
|
+
if (mapping.idToName.has(key2)) {
|
|
4892
|
+
result[mapping.idToName.get(key2)] = value;
|
|
4053
4893
|
} else {
|
|
4054
|
-
result[
|
|
4894
|
+
result[key2] = value;
|
|
4055
4895
|
}
|
|
4056
4896
|
}
|
|
4057
4897
|
return result;
|
|
4058
4898
|
},
|
|
4059
|
-
translateFieldKey(
|
|
4060
|
-
if (!mapping) return
|
|
4061
|
-
if (FIELD_ID_PATTERN.test(
|
|
4062
|
-
const fieldType = mapping.idToType.get(
|
|
4899
|
+
translateFieldKey(key2) {
|
|
4900
|
+
if (!mapping) return key2;
|
|
4901
|
+
if (FIELD_ID_PATTERN.test(key2) && mapping.idToName.has(key2)) {
|
|
4902
|
+
const fieldType = mapping.idToType.get(key2);
|
|
4063
4903
|
if (fieldType) {
|
|
4064
4904
|
const components = NESTED_COMPONENTS[fieldType];
|
|
4065
4905
|
if (components?.size === 1) {
|
|
4066
|
-
return `${
|
|
4906
|
+
return `${key2}__${[...components][0]}`;
|
|
4067
4907
|
}
|
|
4068
4908
|
}
|
|
4069
|
-
return
|
|
4909
|
+
return key2;
|
|
4070
4910
|
}
|
|
4071
|
-
if (mapping.nameToId.has(
|
|
4072
|
-
const fieldId = mapping.nameToId.get(
|
|
4911
|
+
if (mapping.nameToId.has(key2)) {
|
|
4912
|
+
const fieldId = mapping.nameToId.get(key2);
|
|
4073
4913
|
const fieldType = mapping.idToType.get(fieldId);
|
|
4074
4914
|
if (fieldType) {
|
|
4075
4915
|
const components = NESTED_COMPONENTS[fieldType];
|
|
@@ -4079,10 +4919,10 @@ async function createFieldKeyTranslator({
|
|
|
4079
4919
|
}
|
|
4080
4920
|
return fieldId;
|
|
4081
4921
|
}
|
|
4082
|
-
const sepIndex =
|
|
4922
|
+
const sepIndex = key2.lastIndexOf("__");
|
|
4083
4923
|
if (sepIndex > 0) {
|
|
4084
|
-
const prefix =
|
|
4085
|
-
const component =
|
|
4924
|
+
const prefix = key2.slice(0, sepIndex);
|
|
4925
|
+
const component = key2.slice(sepIndex + 2);
|
|
4086
4926
|
let fieldId;
|
|
4087
4927
|
if (FIELD_ID_PATTERN.test(prefix) && mapping.idToName.has(prefix)) {
|
|
4088
4928
|
fieldId = prefix;
|
|
@@ -4096,7 +4936,7 @@ async function createFieldKeyTranslator({
|
|
|
4096
4936
|
}
|
|
4097
4937
|
}
|
|
4098
4938
|
}
|
|
4099
|
-
return
|
|
4939
|
+
return key2;
|
|
4100
4940
|
}
|
|
4101
4941
|
};
|
|
4102
4942
|
}
|
|
@@ -5740,9 +6580,9 @@ var RunActionSchemaDeprecated = zod.z.object({
|
|
|
5740
6580
|
var RunActionInputSchema = zod.z.union([RunActionSchema, RunActionSchemaDeprecated]).describe(RunActionDescription);
|
|
5741
6581
|
|
|
5742
6582
|
// src/formatters/actionResult.ts
|
|
5743
|
-
function getStringProperty(obj,
|
|
5744
|
-
if (typeof obj === "object" && obj !== null &&
|
|
5745
|
-
const value = obj[
|
|
6583
|
+
function getStringProperty(obj, key2) {
|
|
6584
|
+
if (typeof obj === "object" && obj !== null && key2 in obj) {
|
|
6585
|
+
const value = obj[key2];
|
|
5746
6586
|
return typeof value === "string" ? value : void 0;
|
|
5747
6587
|
}
|
|
5748
6588
|
return void 0;
|
|
@@ -5829,13 +6669,13 @@ var runActionPlugin = definePlugin(
|
|
|
5829
6669
|
let oldestKey;
|
|
5830
6670
|
let oldestExpiry = Infinity;
|
|
5831
6671
|
let evictedAny = false;
|
|
5832
|
-
for (const [
|
|
6672
|
+
for (const [key2, entry] of runActionContextCache) {
|
|
5833
6673
|
if (now >= entry.expiresAt) {
|
|
5834
|
-
runActionContextCache.delete(
|
|
6674
|
+
runActionContextCache.delete(key2);
|
|
5835
6675
|
evictedAny = true;
|
|
5836
6676
|
} else if (entry.expiresAt < oldestExpiry) {
|
|
5837
6677
|
oldestExpiry = entry.expiresAt;
|
|
5838
|
-
oldestKey =
|
|
6678
|
+
oldestKey = key2;
|
|
5839
6679
|
}
|
|
5840
6680
|
}
|
|
5841
6681
|
if (!evictedAny && oldestKey) {
|
|
@@ -6236,9 +7076,9 @@ function findManifestEntry({
|
|
|
6236
7076
|
return [slug, manifest.apps[slug]];
|
|
6237
7077
|
}
|
|
6238
7078
|
}
|
|
6239
|
-
for (const [
|
|
7079
|
+
for (const [key2, entry] of Object.entries(manifest.apps)) {
|
|
6240
7080
|
if (entry.implementationName === appKeyWithoutVersion) {
|
|
6241
|
-
return [
|
|
7081
|
+
return [key2, entry];
|
|
6242
7082
|
}
|
|
6243
7083
|
}
|
|
6244
7084
|
return null;
|
|
@@ -6649,28 +7489,28 @@ function censorHeaders(headers) {
|
|
|
6649
7489
|
if (!headers) return headers;
|
|
6650
7490
|
const headersObj = new Headers(headers);
|
|
6651
7491
|
const authKeys = ["authorization", "x-api-key"];
|
|
6652
|
-
for (const [
|
|
6653
|
-
if (authKeys.some((authKey) =>
|
|
7492
|
+
for (const [key2, value] of headersObj.entries()) {
|
|
7493
|
+
if (authKeys.some((authKey) => key2.toLowerCase() === authKey)) {
|
|
6654
7494
|
const spaceIndex = value.indexOf(" ");
|
|
6655
7495
|
if (spaceIndex > 0 && spaceIndex < value.length - 1) {
|
|
6656
7496
|
const prefix = value.substring(0, spaceIndex + 1);
|
|
6657
7497
|
const token = value.substring(spaceIndex + 1);
|
|
6658
7498
|
if (token.length > 12) {
|
|
6659
|
-
const
|
|
7499
|
+
const start2 = token.substring(0, 4);
|
|
6660
7500
|
const end = token.substring(token.length - 4);
|
|
6661
|
-
headersObj.set(
|
|
7501
|
+
headersObj.set(key2, `${prefix}${start2}...${end}`);
|
|
6662
7502
|
} else {
|
|
6663
7503
|
const firstChar = token.charAt(0);
|
|
6664
|
-
headersObj.set(
|
|
7504
|
+
headersObj.set(key2, `${prefix}${firstChar}...`);
|
|
6665
7505
|
}
|
|
6666
7506
|
} else {
|
|
6667
7507
|
if (value.length > 12) {
|
|
6668
|
-
const
|
|
7508
|
+
const start2 = value.substring(0, 4);
|
|
6669
7509
|
const end = value.substring(value.length - 4);
|
|
6670
|
-
headersObj.set(
|
|
7510
|
+
headersObj.set(key2, `${start2}...${end}`);
|
|
6671
7511
|
} else {
|
|
6672
7512
|
const firstChar = value.charAt(0);
|
|
6673
|
-
headersObj.set(
|
|
7513
|
+
headersObj.set(key2, `${firstChar}...`);
|
|
6674
7514
|
}
|
|
6675
7515
|
}
|
|
6676
7516
|
}
|
|
@@ -7239,21 +8079,21 @@ function getClientIdFromCredentials(credentials) {
|
|
|
7239
8079
|
function createMemoryCache() {
|
|
7240
8080
|
const store = /* @__PURE__ */ new Map();
|
|
7241
8081
|
return {
|
|
7242
|
-
async get(
|
|
7243
|
-
const entry = store.get(
|
|
8082
|
+
async get(key2) {
|
|
8083
|
+
const entry = store.get(key2);
|
|
7244
8084
|
if (!entry) return void 0;
|
|
7245
8085
|
if (entry.expiresAt !== void 0 && entry.expiresAt <= Date.now()) {
|
|
7246
|
-
store.delete(
|
|
8086
|
+
store.delete(key2);
|
|
7247
8087
|
return void 0;
|
|
7248
8088
|
}
|
|
7249
8089
|
return { value: entry.value, expiresAt: entry.expiresAt };
|
|
7250
8090
|
},
|
|
7251
|
-
async set(
|
|
8091
|
+
async set(key2, value, options) {
|
|
7252
8092
|
const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
|
|
7253
|
-
store.set(
|
|
8093
|
+
store.set(key2, { value, expiresAt });
|
|
7254
8094
|
},
|
|
7255
|
-
async delete(
|
|
7256
|
-
store.delete(
|
|
8095
|
+
async delete(key2) {
|
|
8096
|
+
store.delete(key2);
|
|
7257
8097
|
}
|
|
7258
8098
|
};
|
|
7259
8099
|
}
|
|
@@ -7744,14 +8584,14 @@ function createSseParserStream() {
|
|
|
7744
8584
|
transform(chunk, controller) {
|
|
7745
8585
|
buffer += chunk;
|
|
7746
8586
|
const newline = /\r\n|\r|\n/g;
|
|
7747
|
-
let
|
|
8587
|
+
let start2 = 0;
|
|
7748
8588
|
let match;
|
|
7749
8589
|
while ((match = newline.exec(buffer)) !== null) {
|
|
7750
8590
|
if (match[0] === "\r" && match.index === buffer.length - 1) break;
|
|
7751
|
-
processLine(buffer.slice(
|
|
7752
|
-
|
|
8591
|
+
processLine(buffer.slice(start2, match.index), controller);
|
|
8592
|
+
start2 = match.index + match[0].length;
|
|
7753
8593
|
}
|
|
7754
|
-
buffer = buffer.slice(
|
|
8594
|
+
buffer = buffer.slice(start2);
|
|
7755
8595
|
},
|
|
7756
8596
|
flush(controller) {
|
|
7757
8597
|
if (buffer.endsWith("\r")) {
|
|
@@ -7853,8 +8693,63 @@ function parseApprovalReviewStreamPayload(parsed, toolNames) {
|
|
|
7853
8693
|
}
|
|
7854
8694
|
}
|
|
7855
8695
|
|
|
8696
|
+
// src/api/deprecation.ts
|
|
8697
|
+
var DEPRECATION_MESSAGE_HEADER = "zapier-sdk-deprecation-message";
|
|
8698
|
+
var DEPRECATION_ID_HEADER = "zapier-sdk-deprecation-id";
|
|
8699
|
+
var DEPRECATION_NOTICE_EVENT = "api:deprecation_notice";
|
|
8700
|
+
var displayedNoticeIds = /* @__PURE__ */ new Set();
|
|
8701
|
+
function handleDeprecationNotice({
|
|
8702
|
+
response,
|
|
8703
|
+
canSendDeprecationMessaging,
|
|
8704
|
+
onEvent
|
|
8705
|
+
}) {
|
|
8706
|
+
try {
|
|
8707
|
+
sniffDeprecationNotice({ response, canSendDeprecationMessaging, onEvent });
|
|
8708
|
+
} catch {
|
|
8709
|
+
}
|
|
8710
|
+
}
|
|
8711
|
+
function sniffDeprecationNotice({
|
|
8712
|
+
response,
|
|
8713
|
+
canSendDeprecationMessaging,
|
|
8714
|
+
onEvent
|
|
8715
|
+
}) {
|
|
8716
|
+
if (!canSendDeprecationMessaging) return;
|
|
8717
|
+
const message = response.headers?.get(DEPRECATION_MESSAGE_HEADER);
|
|
8718
|
+
if (!message) return;
|
|
8719
|
+
const id = response.headers.get(DEPRECATION_ID_HEADER) ?? message;
|
|
8720
|
+
if (!displayedNoticeIds.has(id)) {
|
|
8721
|
+
displayedNoticeIds.add(id);
|
|
8722
|
+
console.warn(`[zapier-sdk] Deprecation: ${message}`);
|
|
8723
|
+
}
|
|
8724
|
+
if (onEvent) {
|
|
8725
|
+
const payload = { id, message };
|
|
8726
|
+
const deprecation = parseDeprecationDate(
|
|
8727
|
+
response.headers.get("deprecation")
|
|
8728
|
+
);
|
|
8729
|
+
if (deprecation !== void 0) payload.deprecation = deprecation;
|
|
8730
|
+
const maybePromise = onEvent({
|
|
8731
|
+
type: DEPRECATION_NOTICE_EVENT,
|
|
8732
|
+
payload: { ...payload },
|
|
8733
|
+
timestamp: Date.now()
|
|
8734
|
+
});
|
|
8735
|
+
if (isPromiseLike(maybePromise)) {
|
|
8736
|
+
void Promise.resolve(maybePromise).catch(() => {
|
|
8737
|
+
});
|
|
8738
|
+
}
|
|
8739
|
+
}
|
|
8740
|
+
}
|
|
8741
|
+
function isPromiseLike(value) {
|
|
8742
|
+
return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
8743
|
+
}
|
|
8744
|
+
function parseDeprecationDate(value) {
|
|
8745
|
+
if (!value) return void 0;
|
|
8746
|
+
const match = /^@(-?\d+)$/.exec(value.trim());
|
|
8747
|
+
if (!match) return void 0;
|
|
8748
|
+
return Number(match[1]) * 1e3;
|
|
8749
|
+
}
|
|
8750
|
+
|
|
7856
8751
|
// src/sdk-version.ts
|
|
7857
|
-
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.
|
|
8752
|
+
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.80.0" : void 0) || "unknown";
|
|
7858
8753
|
|
|
7859
8754
|
// src/utils/open-url.ts
|
|
7860
8755
|
var nodePrefix = "node:";
|
|
@@ -7966,6 +8861,30 @@ var PollApprovalResponseSchema = zod.z.object({
|
|
|
7966
8861
|
reason: zod.z.string().optional()
|
|
7967
8862
|
});
|
|
7968
8863
|
var APPROVAL_MAX_POLLING_INTERVAL_MS = 5e3;
|
|
8864
|
+
function validateSdkPath(path) {
|
|
8865
|
+
if (!path.startsWith("/") || path.startsWith("//")) {
|
|
8866
|
+
throw new ZapierValidationError(
|
|
8867
|
+
`fetch expects a path starting with a single '/', got: ${path}`
|
|
8868
|
+
);
|
|
8869
|
+
}
|
|
8870
|
+
}
|
|
8871
|
+
function findPathConfigEntries({
|
|
8872
|
+
path,
|
|
8873
|
+
matchResolvedGatewayPath = false
|
|
8874
|
+
}) {
|
|
8875
|
+
const pathSegments = path.split("/").filter(Boolean);
|
|
8876
|
+
return Object.entries(pathConfig).filter(([configPath, config]) => {
|
|
8877
|
+
if (!matchResolvedGatewayPath) {
|
|
8878
|
+
return path === configPath || path.startsWith(`${configPath}/`);
|
|
8879
|
+
}
|
|
8880
|
+
const prefixSegments = (config.pathPrefix ?? configPath).split("/").filter(Boolean);
|
|
8881
|
+
return pathSegments.some(
|
|
8882
|
+
(_, startIndex) => prefixSegments.every(
|
|
8883
|
+
(segment, offset) => pathSegments[startIndex + offset] === segment
|
|
8884
|
+
)
|
|
8885
|
+
);
|
|
8886
|
+
}).map(([configPath, config]) => ({ configPath, config }));
|
|
8887
|
+
}
|
|
7969
8888
|
function parseRateLimitHeaders(response) {
|
|
7970
8889
|
const info = {};
|
|
7971
8890
|
const retryAfter = response.headers.get("retry-after");
|
|
@@ -8010,8 +8929,18 @@ var pathConfig = {
|
|
|
8010
8929
|
// e.g. /relay -> https://sdkapi.zapier.com/api/v0/sdk/relay/...
|
|
8011
8930
|
"/relay": {
|
|
8012
8931
|
authHeader: "X-Relay-Authorization",
|
|
8013
|
-
pathPrefix: "/api/v0/sdk/relay"
|
|
8932
|
+
pathPrefix: "/api/v0/sdk/relay",
|
|
8933
|
+
omitDeprecationMessaging: true
|
|
8934
|
+
},
|
|
8935
|
+
// The concrete gateway form of the relay route. Callers that pass the
|
|
8936
|
+
// already-prefixed path reach the same third-party upstreams, so it must
|
|
8937
|
+
// classify as relay too; without this entry it would match nothing and
|
|
8938
|
+
// sniff deprecation headers off a relay response.
|
|
8939
|
+
"/api/v0/sdk/relay": {
|
|
8940
|
+
omitDeprecationMessaging: true
|
|
8014
8941
|
},
|
|
8942
|
+
// Concrete sdkapi routes that do not live behind /api/v0/sdk/<service>.
|
|
8943
|
+
"/api/v0": {},
|
|
8015
8944
|
// e.g. /zapier -> https://sdkapi.zapier.com/api/v0/sdk/zapier/...
|
|
8016
8945
|
"/zapier": {
|
|
8017
8946
|
authHeader: "Authorization",
|
|
@@ -8066,11 +8995,11 @@ var ZapierApiClient = class {
|
|
|
8066
8995
|
);
|
|
8067
8996
|
const inputHeaders = new Headers(init?.headers ?? {});
|
|
8068
8997
|
const mergedHeaders = new Headers();
|
|
8069
|
-
builtHeaders.forEach((value,
|
|
8070
|
-
mergedHeaders.set(
|
|
8998
|
+
builtHeaders.forEach((value, key2) => {
|
|
8999
|
+
mergedHeaders.set(key2, value);
|
|
8071
9000
|
});
|
|
8072
|
-
inputHeaders.forEach((value,
|
|
8073
|
-
mergedHeaders.set(
|
|
9001
|
+
inputHeaders.forEach((value, key2) => {
|
|
9002
|
+
mergedHeaders.set(key2, value);
|
|
8074
9003
|
});
|
|
8075
9004
|
this.applyTelemetryHeaders(mergedHeaders);
|
|
8076
9005
|
let retries = 0;
|
|
@@ -8160,17 +9089,50 @@ var ZapierApiClient = class {
|
|
|
8160
9089
|
* parallelism into the queue.
|
|
8161
9090
|
*/
|
|
8162
9091
|
this.rawFetch = async (path, init) => {
|
|
8163
|
-
|
|
8164
|
-
throw new ZapierValidationError(
|
|
8165
|
-
`fetch expects a path starting with '/', got: ${path}`
|
|
8166
|
-
);
|
|
8167
|
-
}
|
|
9092
|
+
validateSdkPath(path);
|
|
8168
9093
|
const { url, pathConfig: pathConfig2 } = this.buildUrl(path, init?.searchParams);
|
|
8169
9094
|
return this.withSemaphore(
|
|
8170
9095
|
{ url, method: init?.method ?? "GET", signal: init?.signal },
|
|
8171
9096
|
() => this.rawFetchUrl(url, init, pathConfig2)
|
|
8172
9097
|
);
|
|
8173
9098
|
};
|
|
9099
|
+
this.runApprovalFetchLoop = async ({
|
|
9100
|
+
path,
|
|
9101
|
+
init,
|
|
9102
|
+
maxRetries,
|
|
9103
|
+
approvalMode,
|
|
9104
|
+
approvalContext
|
|
9105
|
+
}) => {
|
|
9106
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
9107
|
+
const response = await this.rawFetch(path, init);
|
|
9108
|
+
if (response.status !== 403) {
|
|
9109
|
+
return { response };
|
|
9110
|
+
}
|
|
9111
|
+
const errorType = response.headers.get("x-zapier-error-type");
|
|
9112
|
+
if (errorType !== "approval_required") {
|
|
9113
|
+
return { response };
|
|
9114
|
+
}
|
|
9115
|
+
if (attempt === maxRetries) {
|
|
9116
|
+
return { response };
|
|
9117
|
+
}
|
|
9118
|
+
if (approvalMode === "disabled") {
|
|
9119
|
+
return { response };
|
|
9120
|
+
}
|
|
9121
|
+
if (!approvalContext) {
|
|
9122
|
+
return { response };
|
|
9123
|
+
}
|
|
9124
|
+
try {
|
|
9125
|
+
await this.runOneApprovalRound(
|
|
9126
|
+
approvalContext,
|
|
9127
|
+
approvalMode,
|
|
9128
|
+
init?.signal ?? void 0
|
|
9129
|
+
);
|
|
9130
|
+
} catch (error) {
|
|
9131
|
+
return { response, approvalRoundError: error };
|
|
9132
|
+
}
|
|
9133
|
+
}
|
|
9134
|
+
throw new ZapierApiError("Approval retry loop ended unexpectedly");
|
|
9135
|
+
};
|
|
8174
9136
|
/**
|
|
8175
9137
|
* Approval-aware HTTP fetch.
|
|
8176
9138
|
*
|
|
@@ -8200,46 +9162,62 @@ var ZapierApiClient = class {
|
|
|
8200
9162
|
* `max_retries_exceeded` instead.
|
|
8201
9163
|
*/
|
|
8202
9164
|
this.fetch = async (path, init) => {
|
|
9165
|
+
validateSdkPath(path);
|
|
8203
9166
|
const maxRetries = this.options.maxApprovalRetries ?? DEFAULT_MAX_APPROVAL_RETRIES;
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
}
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
9167
|
+
const { canSendDeprecationMessaging } = this.buildUrl(
|
|
9168
|
+
path,
|
|
9169
|
+
init?.searchParams
|
|
9170
|
+
);
|
|
9171
|
+
const approvalMode = this.options.approvalMode ?? getZapierApprovalMode() ?? getZapierDefaultApprovalMode();
|
|
9172
|
+
const approvalContext = init?.approvalContext;
|
|
9173
|
+
const { response, approvalRoundError } = await this.runApprovalFetchLoop({
|
|
9174
|
+
path,
|
|
9175
|
+
init,
|
|
9176
|
+
maxRetries,
|
|
9177
|
+
approvalMode,
|
|
9178
|
+
approvalContext
|
|
9179
|
+
});
|
|
9180
|
+
handleDeprecationNotice({
|
|
9181
|
+
response,
|
|
9182
|
+
canSendDeprecationMessaging,
|
|
9183
|
+
onEvent: this.options.onEvent
|
|
9184
|
+
});
|
|
9185
|
+
if (response.status !== 403) {
|
|
9186
|
+
return response;
|
|
9187
|
+
}
|
|
9188
|
+
const errorType = response.headers.get("x-zapier-error-type");
|
|
9189
|
+
if (errorType === "request_denied_by_policy") {
|
|
9190
|
+
const { data } = await this.parseResult(response);
|
|
9191
|
+
const { message, errors } = this.parseErrorResponse({
|
|
9192
|
+
status: response.status,
|
|
9193
|
+
statusText: response.statusText,
|
|
9194
|
+
data
|
|
9195
|
+
});
|
|
9196
|
+
throw new ZapierApprovalError(
|
|
9197
|
+
message || "Request explicitly denied by policy",
|
|
9198
|
+
{
|
|
9199
|
+
status: "policy_denied",
|
|
9200
|
+
statusCode: response.status,
|
|
9201
|
+
errors
|
|
9202
|
+
}
|
|
9203
|
+
);
|
|
9204
|
+
}
|
|
9205
|
+
if (errorType !== "approval_required") {
|
|
9206
|
+
return response;
|
|
9207
|
+
}
|
|
9208
|
+
if (approvalRoundError) {
|
|
9209
|
+
throw approvalRoundError;
|
|
9210
|
+
}
|
|
9211
|
+
if (approvalMode === "disabled") {
|
|
9212
|
+
throw new ZapierApprovalError(
|
|
9213
|
+
"Approvals are disabled. Set approvalMode to 'poll' or 'throw' (or ZAPIER_APPROVAL_MODE) to enable.",
|
|
9214
|
+
{ status: "approval_required" }
|
|
9215
|
+
);
|
|
9216
|
+
}
|
|
9217
|
+
if (!approvalContext) {
|
|
9218
|
+
throw new ZapierApiError(
|
|
9219
|
+
`Received 403 approval_required for ${path}, but the caller did not provide an approvalContext builder. Every approval-capable request must pass approvalContext so the SDK can create the approval with the correct policy context.`,
|
|
9220
|
+
{ statusCode: 403 }
|
|
8243
9221
|
);
|
|
8244
9222
|
}
|
|
8245
9223
|
throw new ZapierApprovalError(
|
|
@@ -8501,40 +9479,60 @@ var ZapierApiClient = class {
|
|
|
8501
9479
|
}
|
|
8502
9480
|
// Apply any special routing logic for configured paths.
|
|
8503
9481
|
applyPathConfiguration(path) {
|
|
8504
|
-
const
|
|
8505
|
-
|
|
8506
|
-
)
|
|
8507
|
-
|
|
9482
|
+
const matchingPathEntries = findPathConfigEntries({ path });
|
|
9483
|
+
const routingMatch = matchingPathEntries[0];
|
|
9484
|
+
const buildResult = (url2) => {
|
|
9485
|
+
const resolvedPathEntries = findPathConfigEntries({
|
|
9486
|
+
path: url2.pathname,
|
|
9487
|
+
matchResolvedGatewayPath: true
|
|
9488
|
+
});
|
|
9489
|
+
const deprecationPathMatches = [
|
|
9490
|
+
...matchingPathEntries,
|
|
9491
|
+
...resolvedPathEntries
|
|
9492
|
+
];
|
|
9493
|
+
const canSendDeprecationMessaging = deprecationPathMatches.length > 0 && deprecationPathMatches.every(
|
|
9494
|
+
({ config }) => config.omitDeprecationMessaging !== true
|
|
9495
|
+
);
|
|
9496
|
+
return {
|
|
9497
|
+
url: url2,
|
|
9498
|
+
pathConfig: routingMatch?.config,
|
|
9499
|
+
canSendDeprecationMessaging
|
|
9500
|
+
};
|
|
9501
|
+
};
|
|
8508
9502
|
let finalPath = path;
|
|
8509
|
-
if (config
|
|
8510
|
-
const pathWithoutPrefix = path.slice(
|
|
8511
|
-
finalPath = `${config.pathPrefix}${pathWithoutPrefix}`;
|
|
9503
|
+
if (routingMatch?.config.pathPrefix) {
|
|
9504
|
+
const pathWithoutPrefix = path.slice(routingMatch.configPath.length) || "/";
|
|
9505
|
+
finalPath = `${routingMatch.config.pathPrefix}${pathWithoutPrefix}`;
|
|
8512
9506
|
}
|
|
8513
9507
|
const zapierBaseUrl = getZapierBaseUrl(this.options.baseUrl);
|
|
8514
9508
|
if (zapierBaseUrl === this.options.baseUrl.replace(/\/$/, "")) {
|
|
8515
9509
|
const originalBaseUrl = new URL(this.options.baseUrl);
|
|
8516
9510
|
const finalBaseUrl = `https://sdkapi.${originalBaseUrl.hostname}`;
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
pathConfig: config
|
|
8520
|
-
};
|
|
9511
|
+
const url2 = new URL(finalPath, finalBaseUrl);
|
|
9512
|
+
return buildResult(url2);
|
|
8521
9513
|
}
|
|
8522
9514
|
const baseUrl = new URL(this.options.baseUrl);
|
|
8523
9515
|
const basePath = baseUrl.pathname.replace(/\/$/, "");
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
pathConfig: config
|
|
8527
|
-
};
|
|
9516
|
+
const url = new URL(basePath + finalPath, baseUrl.origin);
|
|
9517
|
+
return buildResult(url);
|
|
8528
9518
|
}
|
|
8529
9519
|
// Helper to build full URLs and return routing info
|
|
8530
9520
|
buildUrl(path, searchParams) {
|
|
8531
|
-
const {
|
|
9521
|
+
const {
|
|
9522
|
+
url,
|
|
9523
|
+
pathConfig: config,
|
|
9524
|
+
canSendDeprecationMessaging
|
|
9525
|
+
} = this.applyPathConfiguration(path);
|
|
8532
9526
|
if (searchParams) {
|
|
8533
|
-
Object.entries(searchParams).forEach(([
|
|
8534
|
-
url.searchParams.set(
|
|
9527
|
+
Object.entries(searchParams).forEach(([key2, value]) => {
|
|
9528
|
+
url.searchParams.set(key2, value);
|
|
8535
9529
|
});
|
|
8536
9530
|
}
|
|
8537
|
-
return {
|
|
9531
|
+
return {
|
|
9532
|
+
url: url.toString(),
|
|
9533
|
+
pathConfig: config,
|
|
9534
|
+
canSendDeprecationMessaging
|
|
9535
|
+
};
|
|
8538
9536
|
}
|
|
8539
9537
|
// Helper to build headers
|
|
8540
9538
|
async buildHeaders(options = {}, pathConfig2) {
|
|
@@ -9324,36 +10322,36 @@ var createConnectionPlugin = definePlugin(
|
|
|
9324
10322
|
sdk: inner,
|
|
9325
10323
|
options
|
|
9326
10324
|
}) => {
|
|
9327
|
-
const { data:
|
|
10325
|
+
const { data: start2 } = await inner.getConnectionStartUrl({
|
|
9328
10326
|
app: options.app
|
|
9329
10327
|
});
|
|
9330
|
-
setMethodMetadata({ selectedApi:
|
|
10328
|
+
setMethodMetadata({ selectedApi: start2.app });
|
|
9331
10329
|
console.error(
|
|
9332
10330
|
`
|
|
9333
10331
|
Open this URL to complete the connection:
|
|
9334
|
-
${
|
|
10332
|
+
${start2.url}
|
|
9335
10333
|
`
|
|
9336
10334
|
);
|
|
9337
10335
|
const shouldOpen = options.browser === "always" || options.browser === "auto" && shouldOpenBrowser();
|
|
9338
10336
|
if (shouldOpen) {
|
|
9339
10337
|
try {
|
|
9340
|
-
await open_url_default(
|
|
10338
|
+
await open_url_default(start2.url);
|
|
9341
10339
|
} catch {
|
|
9342
10340
|
}
|
|
9343
10341
|
}
|
|
9344
10342
|
const { data: fresh } = await inner.waitForNewConnection({
|
|
9345
|
-
app:
|
|
10343
|
+
app: start2.app,
|
|
9346
10344
|
// Server-stamped mint time: measured on the same clock as a
|
|
9347
10345
|
// connection's `date`, so the freshness check is immune to
|
|
9348
10346
|
// client/server clock skew.
|
|
9349
|
-
startedAt:
|
|
10347
|
+
startedAt: start2.startedAt,
|
|
9350
10348
|
timeoutMs: options.timeoutMs,
|
|
9351
10349
|
pollIntervalMs: options.pollIntervalMs
|
|
9352
10350
|
});
|
|
9353
10351
|
return {
|
|
9354
10352
|
data: CreateConnectionItemSchema.parse({
|
|
9355
10353
|
id: fresh.id,
|
|
9356
|
-
app:
|
|
10354
|
+
app: start2.app,
|
|
9357
10355
|
title: fresh.title ?? null
|
|
9358
10356
|
})
|
|
9359
10357
|
};
|
|
@@ -10289,21 +11287,21 @@ var updateTableRecordsPlugin = definePlugin(
|
|
|
10289
11287
|
);
|
|
10290
11288
|
|
|
10291
11289
|
// src/plugins/capabilities/index.ts
|
|
10292
|
-
function toDescription(
|
|
10293
|
-
const words =
|
|
11290
|
+
function toDescription(key2) {
|
|
11291
|
+
const words = key2.replace(/^can/, "").replace(/([A-Z])/g, " $1").trim().toLowerCase();
|
|
10294
11292
|
return `To ${words}`;
|
|
10295
11293
|
}
|
|
10296
|
-
function toEnvVar(
|
|
10297
|
-
return "ZAPIER_" +
|
|
11294
|
+
function toEnvVar(key2) {
|
|
11295
|
+
return "ZAPIER_" + key2.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
10298
11296
|
}
|
|
10299
|
-
function toCliFlag(
|
|
10300
|
-
return "--" +
|
|
11297
|
+
function toCliFlag(key2) {
|
|
11298
|
+
return "--" + key2.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
10301
11299
|
}
|
|
10302
|
-
function buildCapabilityMessage(
|
|
11300
|
+
function buildCapabilityMessage(key2) {
|
|
10303
11301
|
return [
|
|
10304
|
-
`${toDescription(
|
|
10305
|
-
`set ${
|
|
10306
|
-
`or set ${toEnvVar(
|
|
11302
|
+
`${toDescription(key2)}, use ${toCliFlag(key2)} in the CLI,`,
|
|
11303
|
+
`set ${key2}: true in SDK options or .zapierrc,`,
|
|
11304
|
+
`or set ${toEnvVar(key2)}=true.`
|
|
10307
11305
|
].join(" ");
|
|
10308
11306
|
}
|
|
10309
11307
|
var GATED_FLAGS = [
|
|
@@ -10311,8 +11309,8 @@ var GATED_FLAGS = [
|
|
|
10311
11309
|
"canIncludeSharedTables",
|
|
10312
11310
|
"canDeleteTables"
|
|
10313
11311
|
];
|
|
10314
|
-
function isEnabledByEnv(
|
|
10315
|
-
const value = globalThis.process?.env?.[toEnvVar(
|
|
11312
|
+
function isEnabledByEnv(key2) {
|
|
11313
|
+
const value = globalThis.process?.env?.[toEnvVar(key2)];
|
|
10316
11314
|
if (value === void 0) return void 0;
|
|
10317
11315
|
if (value === "true" || value === "1") return true;
|
|
10318
11316
|
if (value === "false" || value === "0") return false;
|
|
@@ -10335,17 +11333,17 @@ var capabilitiesPlugin = definePlugin(
|
|
|
10335
11333
|
}
|
|
10336
11334
|
return {
|
|
10337
11335
|
context: {
|
|
10338
|
-
checkCapability: async (
|
|
11336
|
+
checkCapability: async (key2) => {
|
|
10339
11337
|
const flags = await resolveFlags();
|
|
10340
|
-
if (flags[
|
|
11338
|
+
if (flags[key2]) return;
|
|
10341
11339
|
throw new ZapierConfigurationError(
|
|
10342
|
-
buildCapabilityMessage(
|
|
10343
|
-
{ configType:
|
|
11340
|
+
buildCapabilityMessage(key2) + " (If you are an AI agent, you MUST NOT retry. Ask the user if they want to enable this.)",
|
|
11341
|
+
{ configType: key2 }
|
|
10344
11342
|
);
|
|
10345
11343
|
},
|
|
10346
|
-
hasCapability: async (
|
|
11344
|
+
hasCapability: async (key2) => {
|
|
10347
11345
|
const flags = await resolveFlags();
|
|
10348
|
-
return flags[
|
|
11346
|
+
return flags[key2];
|
|
10349
11347
|
}
|
|
10350
11348
|
}
|
|
10351
11349
|
};
|
|
@@ -10503,8 +11501,8 @@ function getOsInfo() {
|
|
|
10503
11501
|
function getPlatformVersions() {
|
|
10504
11502
|
const versions = {};
|
|
10505
11503
|
if (typeof globalThis.process?.versions === "object") {
|
|
10506
|
-
for (const [
|
|
10507
|
-
versions[
|
|
11504
|
+
for (const [key2, value] of Object.entries(globalThis.process.versions)) {
|
|
11505
|
+
versions[key2] = value || null;
|
|
10508
11506
|
}
|
|
10509
11507
|
}
|
|
10510
11508
|
return versions;
|
|
@@ -10746,9 +11744,9 @@ async function emitWithTimeout(transport, subject, event) {
|
|
|
10746
11744
|
}
|
|
10747
11745
|
function mergeUserContext(event, userContext) {
|
|
10748
11746
|
const merged = { ...event };
|
|
10749
|
-
for (const [
|
|
10750
|
-
if (merged[
|
|
10751
|
-
merged[
|
|
11747
|
+
for (const [key2, value] of Object.entries(userContext)) {
|
|
11748
|
+
if (merged[key2] == null) {
|
|
11749
|
+
merged[key2] = value;
|
|
10752
11750
|
}
|
|
10753
11751
|
}
|
|
10754
11752
|
return merged;
|
|
@@ -11264,13 +12262,16 @@ exports.BaseSdkOptionsSchema = BaseSdkOptionsSchema;
|
|
|
11264
12262
|
exports.CONTEXT_CACHE_MAX_SIZE = CONTEXT_CACHE_MAX_SIZE;
|
|
11265
12263
|
exports.CONTEXT_CACHE_TTL_MS = CONTEXT_CACHE_TTL_MS;
|
|
11266
12264
|
exports.CORE_ERROR_SYMBOL = CORE_ERROR_SYMBOL;
|
|
12265
|
+
exports.CORE_SIGNAL_SYMBOL = CORE_SIGNAL_SYMBOL;
|
|
11267
12266
|
exports.ClientCredentialsObjectSchema = ClientCredentialsObjectSchema;
|
|
11268
12267
|
exports.ConnectionEntrySchema = ConnectionEntrySchema;
|
|
11269
12268
|
exports.ConnectionIdPropertySchema = ConnectionIdPropertySchema;
|
|
11270
12269
|
exports.ConnectionPropertySchema = ConnectionPropertySchema;
|
|
11271
12270
|
exports.ConnectionsMapSchema = ConnectionsMapSchema;
|
|
11272
12271
|
exports.ConnectionsPropertySchema = ConnectionsPropertySchema;
|
|
12272
|
+
exports.CoreCancelledSignal = CoreCancelledSignal;
|
|
11273
12273
|
exports.CoreErrorCode = CoreErrorCode;
|
|
12274
|
+
exports.CoreSignal = CoreSignal;
|
|
11274
12275
|
exports.CredentialsFunctionSchema = CredentialsFunctionSchema;
|
|
11275
12276
|
exports.CredentialsObjectSchema = CredentialsObjectSchema;
|
|
11276
12277
|
exports.CredentialsSchema = CredentialsSchema;
|
|
@@ -11279,6 +12280,7 @@ exports.DEFAULT_APPROVAL_TIMEOUT_MS = DEFAULT_APPROVAL_TIMEOUT_MS;
|
|
|
11279
12280
|
exports.DEFAULT_CONFIG_PATH = DEFAULT_CONFIG_PATH;
|
|
11280
12281
|
exports.DEFAULT_MAX_APPROVAL_RETRIES = DEFAULT_MAX_APPROVAL_RETRIES;
|
|
11281
12282
|
exports.DEFAULT_PAGE_SIZE = DEFAULT_PAGE_SIZE;
|
|
12283
|
+
exports.DEPRECATION_NOTICE_EVENT = DEPRECATION_NOTICE_EVENT;
|
|
11282
12284
|
exports.DebugPropertySchema = DebugPropertySchema;
|
|
11283
12285
|
exports.FieldsPropertySchema = FieldsPropertySchema;
|
|
11284
12286
|
exports.InputFieldPropertySchema = InputFieldPropertySchema;
|
|
@@ -11349,6 +12351,7 @@ exports.connectionIdResolver = connectionIdResolver;
|
|
|
11349
12351
|
exports.connectionsPlugin = connectionsPlugin;
|
|
11350
12352
|
exports.createBaseEvent = createBaseEvent;
|
|
11351
12353
|
exports.createClientCredentialsPlugin = createClientCredentialsPlugin;
|
|
12354
|
+
exports.createController = createController;
|
|
11352
12355
|
exports.createCorePlugin = createCorePlugin;
|
|
11353
12356
|
exports.createFunction = createFunction;
|
|
11354
12357
|
exports.createMemoryCache = createMemoryCache;
|
|
@@ -11372,6 +12375,7 @@ exports.defineLegacyMerge = defineLegacyMerge;
|
|
|
11372
12375
|
exports.defineMethod = defineMethod;
|
|
11373
12376
|
exports.definePlugin = definePlugin;
|
|
11374
12377
|
exports.defineProperty = defineProperty;
|
|
12378
|
+
exports.defineResolver = defineResolver;
|
|
11375
12379
|
exports.deleteClientCredentialsPlugin = deleteClientCredentialsPlugin;
|
|
11376
12380
|
exports.deleteTableFieldsPlugin = deleteTableFieldsPlugin;
|
|
11377
12381
|
exports.deleteTablePlugin = deleteTablePlugin;
|
|
@@ -11424,6 +12428,7 @@ exports.isCi = isCi;
|
|
|
11424
12428
|
exports.isCliLoginAvailable = isCliLoginAvailable;
|
|
11425
12429
|
exports.isClientCredentials = isClientCredentials;
|
|
11426
12430
|
exports.isCoreError = isCoreError;
|
|
12431
|
+
exports.isCoreSignal = isCoreSignal;
|
|
11427
12432
|
exports.isCredentialsFunction = isCredentialsFunction;
|
|
11428
12433
|
exports.isCredentialsObject = isCredentialsObject;
|
|
11429
12434
|
exports.isPermanentHttpError = isPermanentHttpError;
|