@zapier/kitcore 0.10.1 → 0.12.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 +27 -0
- package/README.md +63 -5
- package/dist/index.cjs +486 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +252 -26
- package/dist/index.d.ts +252 -26
- package/dist/index.mjs +484 -98
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -49,7 +49,9 @@ __export(index_exports, {
|
|
|
49
49
|
createSdk: () => createSdk,
|
|
50
50
|
createValidator: () => createValidator,
|
|
51
51
|
dangerousContextPlugin: () => dangerousContextPlugin,
|
|
52
|
+
declareDefault: () => declareDefault,
|
|
52
53
|
declareMethod: () => declareMethod,
|
|
54
|
+
declareOptionalMethod: () => declareOptionalMethod,
|
|
53
55
|
declareOptionalProperty: () => declareOptionalProperty,
|
|
54
56
|
declarePlugin: () => declarePlugin,
|
|
55
57
|
declareProperty: () => declareProperty,
|
|
@@ -299,12 +301,19 @@ function composeVoid(existing, added) {
|
|
|
299
301
|
isolated.add(composed);
|
|
300
302
|
return composed;
|
|
301
303
|
}
|
|
304
|
+
function composeAnnotators(existing, added) {
|
|
305
|
+
if (!existing) return added;
|
|
306
|
+
if (!added) return existing;
|
|
307
|
+
return (ctx) => ({ ...existing(ctx), ...added(ctx) });
|
|
308
|
+
}
|
|
302
309
|
function buildHooks(existing, added) {
|
|
303
310
|
const result = {};
|
|
304
311
|
const start2 = composeVoid(existing.onMethodStart, added.onMethodStart);
|
|
305
312
|
if (start2) result.onMethodStart = start2;
|
|
306
313
|
const end = composeVoid(existing.onMethodEnd, added.onMethodEnd);
|
|
307
314
|
if (end) result.onMethodEnd = end;
|
|
315
|
+
const annotator = composeAnnotators(existing.annotator, added.annotator);
|
|
316
|
+
if (annotator) result.annotator = annotator;
|
|
308
317
|
return result;
|
|
309
318
|
}
|
|
310
319
|
|
|
@@ -777,11 +786,14 @@ function generateCallId() {
|
|
|
777
786
|
}
|
|
778
787
|
return null;
|
|
779
788
|
}
|
|
780
|
-
function rootCallContext(
|
|
789
|
+
function rootCallContext({
|
|
790
|
+
callOrigin = "surface"
|
|
791
|
+
} = {}) {
|
|
781
792
|
return {
|
|
782
793
|
callId: generateCallId(),
|
|
783
794
|
depth: 0,
|
|
784
795
|
annotations: {},
|
|
796
|
+
callOrigin,
|
|
785
797
|
[CALL_CONTEXT_BRAND]: true
|
|
786
798
|
};
|
|
787
799
|
}
|
|
@@ -790,6 +802,7 @@ function childCallContext(parent) {
|
|
|
790
802
|
callId: parent.callId,
|
|
791
803
|
depth: parent.depth + 1,
|
|
792
804
|
annotations: {},
|
|
805
|
+
callOrigin: parent.callOrigin,
|
|
793
806
|
[CALL_CONTEXT_BRAND]: true
|
|
794
807
|
};
|
|
795
808
|
}
|
|
@@ -815,6 +828,28 @@ var INTERNAL_CALL = Symbol("kitcore.internalCall");
|
|
|
815
828
|
function resolveCallContext(secondArg) {
|
|
816
829
|
return isCallContext(secondArg) ? secondArg : rootCallContext();
|
|
817
830
|
}
|
|
831
|
+
var hookAnnotatorReentrancy = 0;
|
|
832
|
+
function applyAnnotations({
|
|
833
|
+
context,
|
|
834
|
+
methodName,
|
|
835
|
+
input,
|
|
836
|
+
hookAnnotator,
|
|
837
|
+
methodAnnotator
|
|
838
|
+
}) {
|
|
839
|
+
if (hookAnnotator && !isInsideObserver() && context.depth === 0 && context.callOrigin !== "internal" && hookAnnotatorReentrancy === 0) {
|
|
840
|
+
hookAnnotatorReentrancy++;
|
|
841
|
+
try {
|
|
842
|
+
Object.assign(context.annotations, hookAnnotator({ methodName, input }));
|
|
843
|
+
} catch {
|
|
844
|
+
} finally {
|
|
845
|
+
hookAnnotatorReentrancy--;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
try {
|
|
849
|
+
Object.assign(context.annotations, methodAnnotator?.(input));
|
|
850
|
+
} catch {
|
|
851
|
+
}
|
|
852
|
+
}
|
|
818
853
|
function signalDeprecation(context, methodName, getDeprecation) {
|
|
819
854
|
if (isInsideObserver()) return;
|
|
820
855
|
const deprecation = getDeprecation?.();
|
|
@@ -840,7 +875,7 @@ function normalizeError(error, adaptError) {
|
|
|
840
875
|
);
|
|
841
876
|
}
|
|
842
877
|
function createFunction(coreFn, options) {
|
|
843
|
-
const { sdk, schema, name, getDeprecation } = options;
|
|
878
|
+
const { sdk, schema, name, annotator, getDeprecation } = options;
|
|
844
879
|
const functionName = name || coreFn.name;
|
|
845
880
|
const namedFunctions = {
|
|
846
881
|
[functionName]: async function(callOptions) {
|
|
@@ -854,14 +889,26 @@ function createFunction(coreFn, options) {
|
|
|
854
889
|
const normalizedOptions = callOptions ?? {};
|
|
855
890
|
const args = [normalizedOptions];
|
|
856
891
|
const depth = Math.max(context.depth, getCurrentDepth());
|
|
857
|
-
const
|
|
892
|
+
const insideObserver = isInsideObserver();
|
|
893
|
+
const hooks = insideObserver ? void 0 : sdk.context.hooks;
|
|
858
894
|
const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
|
|
859
|
-
|
|
895
|
+
applyAnnotations({
|
|
896
|
+
context,
|
|
897
|
+
methodName: functionName,
|
|
898
|
+
input: normalizedOptions,
|
|
899
|
+
hookAnnotator: hooks?.annotator,
|
|
900
|
+
methodAnnotator: annotator
|
|
901
|
+
});
|
|
902
|
+
const hookBase = {
|
|
860
903
|
methodName: functionName,
|
|
861
904
|
args,
|
|
862
905
|
isPaginated: false,
|
|
863
|
-
depth
|
|
864
|
-
|
|
906
|
+
depth,
|
|
907
|
+
callId: context.callId,
|
|
908
|
+
callOrigin: context.callOrigin,
|
|
909
|
+
annotations: context.annotations
|
|
910
|
+
};
|
|
911
|
+
hooks?.onMethodStart?.({ ...hookBase });
|
|
865
912
|
try {
|
|
866
913
|
let result;
|
|
867
914
|
if (schema) {
|
|
@@ -883,20 +930,14 @@ function createFunction(coreFn, options) {
|
|
|
883
930
|
result = await coreFn(normalizedOptions, context);
|
|
884
931
|
}
|
|
885
932
|
hooks?.onMethodEnd?.({
|
|
886
|
-
|
|
887
|
-
args,
|
|
888
|
-
isPaginated: false,
|
|
889
|
-
depth,
|
|
933
|
+
...hookBase,
|
|
890
934
|
durationMs: Date.now() - startTime
|
|
891
935
|
});
|
|
892
936
|
return result;
|
|
893
937
|
} catch (error) {
|
|
894
938
|
const normalizedError = normalizeError(error, adaptError);
|
|
895
939
|
hooks?.onMethodEnd?.({
|
|
896
|
-
|
|
897
|
-
args,
|
|
898
|
-
isPaginated: false,
|
|
899
|
-
depth,
|
|
940
|
+
...hookBase,
|
|
900
941
|
durationMs: Date.now() - startTime,
|
|
901
942
|
error: normalizedError
|
|
902
943
|
});
|
|
@@ -908,7 +949,7 @@ function createFunction(coreFn, options) {
|
|
|
908
949
|
return namedFunctions[functionName];
|
|
909
950
|
}
|
|
910
951
|
function createRawFunction(coreFn, options) {
|
|
911
|
-
const { sdk, name, schema, positional, getDeprecation } = options;
|
|
952
|
+
const { sdk, name, schema, positional, annotator, getDeprecation } = options;
|
|
912
953
|
return function(rawInput) {
|
|
913
954
|
const internal = arguments[1];
|
|
914
955
|
const context = resolveCallContext(internal);
|
|
@@ -918,23 +959,32 @@ function createRawFunction(coreFn, options) {
|
|
|
918
959
|
return runInMethodScope(() => {
|
|
919
960
|
const startTime = Date.now();
|
|
920
961
|
const depth = Math.max(context.depth, getCurrentDepth());
|
|
921
|
-
const
|
|
962
|
+
const insideObserver = isInsideObserver();
|
|
963
|
+
const hooks = insideObserver ? void 0 : sdk.context.hooks;
|
|
922
964
|
const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
|
|
923
965
|
const input = schema ? rawInput ?? {} : rawInput;
|
|
966
|
+
applyAnnotations({
|
|
967
|
+
context,
|
|
968
|
+
methodName: name,
|
|
969
|
+
input,
|
|
970
|
+
hookAnnotator: hooks?.annotator,
|
|
971
|
+
methodAnnotator: annotator
|
|
972
|
+
});
|
|
924
973
|
const record = input;
|
|
925
974
|
const args = positional ? positional.filter((key) => record?.[key] !== void 0).map((key) => record?.[key]) : [input];
|
|
926
|
-
|
|
975
|
+
const hookBase = {
|
|
927
976
|
methodName: name,
|
|
928
977
|
args,
|
|
929
978
|
isPaginated: false,
|
|
930
|
-
depth
|
|
931
|
-
|
|
979
|
+
depth,
|
|
980
|
+
callId: context.callId,
|
|
981
|
+
callOrigin: context.callOrigin,
|
|
982
|
+
annotations: context.annotations
|
|
983
|
+
};
|
|
984
|
+
hooks?.onMethodStart?.({ ...hookBase });
|
|
932
985
|
const fireEnd = (error) => {
|
|
933
986
|
hooks?.onMethodEnd?.({
|
|
934
|
-
|
|
935
|
-
args,
|
|
936
|
-
isPaginated: false,
|
|
937
|
-
depth,
|
|
987
|
+
...hookBase,
|
|
938
988
|
durationMs: Date.now() - startTime,
|
|
939
989
|
...error ? { error } : {}
|
|
940
990
|
});
|
|
@@ -976,7 +1026,8 @@ function isSdkPage(value) {
|
|
|
976
1026
|
}
|
|
977
1027
|
function createPageFunction(coreFn, {
|
|
978
1028
|
sdk,
|
|
979
|
-
adaptPage
|
|
1029
|
+
adaptPage,
|
|
1030
|
+
finalizePage
|
|
980
1031
|
}) {
|
|
981
1032
|
const functionName = coreFn.name + "Page";
|
|
982
1033
|
const namedFunctions = {
|
|
@@ -989,7 +1040,7 @@ function createPageFunction(coreFn, {
|
|
|
989
1040
|
`${functionName}: paginated result must be exactly { data: TItem[], nextCursor? } (produced by the handler or its \`adaptPage\`); got keys [${page && typeof page === "object" ? Object.keys(page).join(", ") : typeof page}]. If the handler returns a raw shape, set \`adaptPage\` to translate it; if \`adaptPage\` already runs, it must return only \`data\`/\`nextCursor\`.`
|
|
990
1041
|
);
|
|
991
1042
|
}
|
|
992
|
-
return page;
|
|
1043
|
+
return finalizePage ? finalizePage(page) : page;
|
|
993
1044
|
} catch (error) {
|
|
994
1045
|
throw normalizeError(
|
|
995
1046
|
error,
|
|
@@ -1001,8 +1052,21 @@ function createPageFunction(coreFn, {
|
|
|
1001
1052
|
return namedFunctions[functionName];
|
|
1002
1053
|
}
|
|
1003
1054
|
function createPaginatedFunction(coreFn, options) {
|
|
1004
|
-
const {
|
|
1005
|
-
|
|
1055
|
+
const {
|
|
1056
|
+
sdk,
|
|
1057
|
+
schema,
|
|
1058
|
+
name,
|
|
1059
|
+
defaultPageSize,
|
|
1060
|
+
adaptPage,
|
|
1061
|
+
annotator,
|
|
1062
|
+
finalizePage,
|
|
1063
|
+
getDeprecation
|
|
1064
|
+
} = options;
|
|
1065
|
+
const pageFunction = createPageFunction(coreFn, {
|
|
1066
|
+
sdk,
|
|
1067
|
+
adaptPage,
|
|
1068
|
+
finalizePage
|
|
1069
|
+
});
|
|
1006
1070
|
const functionName = name || coreFn.name;
|
|
1007
1071
|
const namedFunctions = {
|
|
1008
1072
|
[functionName]: function(callOptions) {
|
|
@@ -1016,14 +1080,26 @@ function createPaginatedFunction(coreFn, options) {
|
|
|
1016
1080
|
const normalizedOptions = callOptions ?? {};
|
|
1017
1081
|
const args = [normalizedOptions];
|
|
1018
1082
|
const depth = Math.max(context.depth, getCurrentDepth());
|
|
1019
|
-
const
|
|
1083
|
+
const insideObserver = isInsideObserver();
|
|
1084
|
+
const hooks = insideObserver ? void 0 : sdk.context.hooks;
|
|
1020
1085
|
const adaptError = resolveCoreOptions(sdk.context)?.adaptError;
|
|
1021
|
-
|
|
1086
|
+
applyAnnotations({
|
|
1087
|
+
context,
|
|
1088
|
+
methodName: functionName,
|
|
1089
|
+
input: normalizedOptions,
|
|
1090
|
+
hookAnnotator: hooks?.annotator,
|
|
1091
|
+
methodAnnotator: annotator
|
|
1092
|
+
});
|
|
1093
|
+
const hookBase = {
|
|
1022
1094
|
methodName: functionName,
|
|
1023
1095
|
args,
|
|
1024
1096
|
isPaginated: true,
|
|
1025
|
-
depth
|
|
1026
|
-
|
|
1097
|
+
depth,
|
|
1098
|
+
callId: context.callId,
|
|
1099
|
+
callOrigin: context.callOrigin,
|
|
1100
|
+
annotations: context.annotations
|
|
1101
|
+
};
|
|
1102
|
+
hooks?.onMethodStart?.({ ...hookBase });
|
|
1027
1103
|
try {
|
|
1028
1104
|
const validatedOptions = {
|
|
1029
1105
|
...normalizedOptions,
|
|
@@ -1049,19 +1125,13 @@ function createPaginatedFunction(coreFn, options) {
|
|
|
1049
1125
|
firstPagePromise.then(
|
|
1050
1126
|
() => {
|
|
1051
1127
|
hooks.onMethodEnd({
|
|
1052
|
-
|
|
1053
|
-
args,
|
|
1054
|
-
isPaginated: true,
|
|
1055
|
-
depth,
|
|
1128
|
+
...hookBase,
|
|
1056
1129
|
durationMs: Date.now() - startTime
|
|
1057
1130
|
});
|
|
1058
1131
|
},
|
|
1059
1132
|
(error) => {
|
|
1060
1133
|
hooks.onMethodEnd({
|
|
1061
|
-
|
|
1062
|
-
args,
|
|
1063
|
-
isPaginated: true,
|
|
1064
|
-
depth,
|
|
1134
|
+
...hookBase,
|
|
1065
1135
|
durationMs: Date.now() - startTime,
|
|
1066
1136
|
error: error instanceof Error ? error : new Error(String(error))
|
|
1067
1137
|
});
|
|
@@ -1100,10 +1170,7 @@ function createPaginatedFunction(coreFn, options) {
|
|
|
1100
1170
|
} catch (error) {
|
|
1101
1171
|
const normalizedError = normalizeError(error, adaptError);
|
|
1102
1172
|
hooks?.onMethodEnd?.({
|
|
1103
|
-
|
|
1104
|
-
args,
|
|
1105
|
-
isPaginated: true,
|
|
1106
|
-
depth,
|
|
1173
|
+
...hookBase,
|
|
1107
1174
|
durationMs: Date.now() - startTime,
|
|
1108
1175
|
error: normalizedError
|
|
1109
1176
|
});
|
|
@@ -1525,9 +1592,11 @@ function defineMethod(config) {
|
|
|
1525
1592
|
importBindings: deps.bindings,
|
|
1526
1593
|
inputSchema: config.inputSchema,
|
|
1527
1594
|
skipInputValidation: config.skipInputValidation,
|
|
1595
|
+
skipOutputValidation: config.skipOutputValidation,
|
|
1528
1596
|
meta: collectLeafMeta(config),
|
|
1529
1597
|
resolvers: config.resolvers,
|
|
1530
1598
|
formatter: config.formatter,
|
|
1599
|
+
annotator: config.annotator,
|
|
1531
1600
|
output: config.output,
|
|
1532
1601
|
positional: config.positional,
|
|
1533
1602
|
setup: config.setup,
|
|
@@ -1630,6 +1699,29 @@ function declareMethod(config) {
|
|
|
1630
1699
|
}
|
|
1631
1700
|
};
|
|
1632
1701
|
}
|
|
1702
|
+
function declareOptionalMethod(config) {
|
|
1703
|
+
const { name, namespace } = parseId(config.id);
|
|
1704
|
+
const id = makeId(name, namespace);
|
|
1705
|
+
return {
|
|
1706
|
+
pluginType: "method",
|
|
1707
|
+
name,
|
|
1708
|
+
namespace,
|
|
1709
|
+
id,
|
|
1710
|
+
standIn: true,
|
|
1711
|
+
optional: true,
|
|
1712
|
+
imports: [],
|
|
1713
|
+
importBindings: [],
|
|
1714
|
+
run: () => {
|
|
1715
|
+
throw new Error(
|
|
1716
|
+
`Plugin "${id}" is an optional stand-in (declareOptionalMethod) with no implementation. Its binding is \`undefined\` unless a real plugin is registered under this id.`
|
|
1717
|
+
);
|
|
1718
|
+
}
|
|
1719
|
+
// Requires nothing (phantom carrier `<never, never>`): a consumer that
|
|
1720
|
+
// imports it still passes `createSdk`'s completeness check unprovided. The
|
|
1721
|
+
// `optional: true` literal drives `PluginSurface` to type the binding
|
|
1722
|
+
// `| undefined`.
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1633
1725
|
function defineProperty(config) {
|
|
1634
1726
|
const deps = normalizeImports(config.imports);
|
|
1635
1727
|
return {
|
|
@@ -1675,6 +1767,11 @@ function declareOptionalProperty(config) {
|
|
|
1675
1767
|
// import binding is still typed `TValue | undefined` from the descriptor.
|
|
1676
1768
|
};
|
|
1677
1769
|
}
|
|
1770
|
+
function declareDefault({
|
|
1771
|
+
plugin
|
|
1772
|
+
}) {
|
|
1773
|
+
return { ...plugin, defaultSource: plugin };
|
|
1774
|
+
}
|
|
1678
1775
|
function defineHook(config) {
|
|
1679
1776
|
const deps = normalizeImports(config.imports);
|
|
1680
1777
|
return {
|
|
@@ -1687,7 +1784,8 @@ function defineHook(config) {
|
|
|
1687
1784
|
setup: config.setup,
|
|
1688
1785
|
dispose: config.dispose,
|
|
1689
1786
|
wrap: config.wrap,
|
|
1690
|
-
observe: config.observe
|
|
1787
|
+
observe: config.observe,
|
|
1788
|
+
annotator: config.annotator
|
|
1691
1789
|
};
|
|
1692
1790
|
}
|
|
1693
1791
|
function declarePlugin(config) {
|
|
@@ -1975,6 +2073,97 @@ var getRegistryPlugin = defineMethod({
|
|
|
1975
2073
|
run: ({ imports, input }) => buildSurfaceRegistry(imports.context, input?.package)
|
|
1976
2074
|
});
|
|
1977
2075
|
|
|
2076
|
+
// src/utils/output-policy.ts
|
|
2077
|
+
function isRecord(value) {
|
|
2078
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2079
|
+
}
|
|
2080
|
+
function diffDroppedPaths(raw, parsed, prefix = "") {
|
|
2081
|
+
const paths = [];
|
|
2082
|
+
walkDroppedPaths(raw, parsed, prefix, paths);
|
|
2083
|
+
return paths;
|
|
2084
|
+
}
|
|
2085
|
+
function walkDroppedPaths(raw, parsed, prefix, out) {
|
|
2086
|
+
if (Array.isArray(raw) && Array.isArray(parsed)) {
|
|
2087
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2088
|
+
const length = Math.min(raw.length, parsed.length);
|
|
2089
|
+
for (let index = 0; index < length; index++) {
|
|
2090
|
+
const elementPaths = [];
|
|
2091
|
+
walkDroppedPaths(raw[index], parsed[index], `${prefix}[]`, elementPaths);
|
|
2092
|
+
for (const path of elementPaths) {
|
|
2093
|
+
if (seen.has(path)) continue;
|
|
2094
|
+
seen.add(path);
|
|
2095
|
+
out.push(path);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
if (isRecord(raw) && isRecord(parsed)) {
|
|
2101
|
+
for (const key of Object.keys(raw)) {
|
|
2102
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
2103
|
+
if (!(key in parsed)) {
|
|
2104
|
+
out.push(path);
|
|
2105
|
+
continue;
|
|
2106
|
+
}
|
|
2107
|
+
walkDroppedPaths(raw[key], parsed[key], path, out);
|
|
2108
|
+
}
|
|
2109
|
+
return;
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
function parseOutput(schema, value, policy, locator) {
|
|
2113
|
+
const result = schema.safeParse(value);
|
|
2114
|
+
if (result.success) return result.data;
|
|
2115
|
+
const issues = result.error.issues.map((issue) => {
|
|
2116
|
+
const path = issue.path.length > 0 ? issue.path.join(".") : "data";
|
|
2117
|
+
return `${path}: ${issue.message}`;
|
|
2118
|
+
});
|
|
2119
|
+
const subject = policy.methodName ? ` for "${policy.methodName}"` : "";
|
|
2120
|
+
const at = locator ? ` at ${locator}` : "";
|
|
2121
|
+
throw createCoreError(
|
|
2122
|
+
{
|
|
2123
|
+
code: CoreErrorCode.Validation,
|
|
2124
|
+
message: `Output validation failed${subject}${at}:
|
|
2125
|
+
${issues.join("\n ")}
|
|
2126
|
+
|
|
2127
|
+
The response does not match the method's \`outputSchema\`. Correct the schema, or set \`skipOutputValidation: true\` on the method to pass the response through unvalidated.`,
|
|
2128
|
+
details: { zodErrors: result.error.issues, output: value }
|
|
2129
|
+
},
|
|
2130
|
+
policy.adaptError
|
|
2131
|
+
);
|
|
2132
|
+
}
|
|
2133
|
+
function applyItemOutputPolicy(result, policy) {
|
|
2134
|
+
const schema = policy.outputSchema;
|
|
2135
|
+
if (!schema || policy.skipOutputValidation) return result;
|
|
2136
|
+
if (!isRecord(result) || !("data" in result)) return result;
|
|
2137
|
+
const data = parseOutput(schema, result.data, policy);
|
|
2138
|
+
const next = { ...result, data };
|
|
2139
|
+
if (policy.includeOutputValidationDroppedPaths) {
|
|
2140
|
+
const droppedPaths = diffDroppedPaths(result.data, data);
|
|
2141
|
+
if (droppedPaths.length > 0) {
|
|
2142
|
+
next.meta = withOutputValidation(result.meta, droppedPaths);
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
return next;
|
|
2146
|
+
}
|
|
2147
|
+
function withOutputValidation(existing, droppedPaths) {
|
|
2148
|
+
const base = isRecord(existing) ? existing : {};
|
|
2149
|
+
return { ...base, outputValidation: { droppedPaths } };
|
|
2150
|
+
}
|
|
2151
|
+
function applyListOutputPolicy(page, policy) {
|
|
2152
|
+
const schema = policy.outputSchema;
|
|
2153
|
+
if (!schema || policy.skipOutputValidation) return page;
|
|
2154
|
+
const data = page.data.map(
|
|
2155
|
+
(item, index) => parseOutput(schema, item, policy, `data[${index}]`)
|
|
2156
|
+
);
|
|
2157
|
+
const next = { ...page, data };
|
|
2158
|
+
if (policy.includeOutputValidationDroppedPaths) {
|
|
2159
|
+
const droppedPaths = diffDroppedPaths(page.data, data);
|
|
2160
|
+
if (droppedPaths.length > 0) {
|
|
2161
|
+
next.meta = { ...page.meta, outputValidation: { droppedPaths } };
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
return next;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
1978
2167
|
// src/model/materialize.ts
|
|
1979
2168
|
var FRAMEWORK_CONFIGURATION_IDS = /* @__PURE__ */ new Set([
|
|
1980
2169
|
CORE_OPTIONS_ID
|
|
@@ -2038,6 +2227,9 @@ function edgesOf(plugin) {
|
|
|
2038
2227
|
function isStandIn(plugin) {
|
|
2039
2228
|
return (plugin.pluginType === "method" || plugin.pluginType === "property" || plugin.pluginType === "aggregate") && plugin.standIn === true;
|
|
2040
2229
|
}
|
|
2230
|
+
function isDefault(plugin) {
|
|
2231
|
+
return (plugin.pluginType === "method" || plugin.pluginType === "property") && plugin.defaultSource !== void 0;
|
|
2232
|
+
}
|
|
2041
2233
|
function topoOrder(descriptors) {
|
|
2042
2234
|
const order = [];
|
|
2043
2235
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -2052,28 +2244,89 @@ function topoOrder(descriptors) {
|
|
|
2052
2244
|
return order;
|
|
2053
2245
|
}
|
|
2054
2246
|
function collectPlugins(root, materialized = /* @__PURE__ */ new Set(), configuration) {
|
|
2247
|
+
const rank = (plugin) => isStandIn(plugin) ? 0 : isDefault(plugin) ? 1 : 2;
|
|
2248
|
+
const allNodes = [];
|
|
2249
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2250
|
+
const collect = (plugin) => {
|
|
2251
|
+
if (materialized.has(plugin.id) || seen.has(plugin)) return;
|
|
2252
|
+
seen.add(plugin);
|
|
2253
|
+
allNodes.push(plugin);
|
|
2254
|
+
for (const edge of edgesOf(plugin)) collect(edge);
|
|
2255
|
+
};
|
|
2256
|
+
collect(root);
|
|
2257
|
+
const childrenOf = /* @__PURE__ */ new Map();
|
|
2258
|
+
const candidatesById = /* @__PURE__ */ new Map();
|
|
2259
|
+
for (const node of allNodes) {
|
|
2260
|
+
childrenOf.set(
|
|
2261
|
+
node,
|
|
2262
|
+
edgesOf(node).filter((edge) => seen.has(edge))
|
|
2263
|
+
);
|
|
2264
|
+
const candidates = candidatesById.get(node.id);
|
|
2265
|
+
if (candidates) candidates.push(node);
|
|
2266
|
+
else candidatesById.set(node.id, [node]);
|
|
2267
|
+
}
|
|
2268
|
+
const live = new Set(allNodes);
|
|
2269
|
+
for (; ; ) {
|
|
2270
|
+
const reachable = /* @__PURE__ */ new Set();
|
|
2271
|
+
if (live.has(root)) reachable.add(root);
|
|
2272
|
+
const queue = reachable.has(root) ? [root] : [];
|
|
2273
|
+
while (queue.length) {
|
|
2274
|
+
const node = queue.pop();
|
|
2275
|
+
for (const child of childrenOf.get(node) ?? []) {
|
|
2276
|
+
if (reachable.has(child)) continue;
|
|
2277
|
+
reachable.add(child);
|
|
2278
|
+
if (live.has(child)) queue.push(child);
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
let changed = false;
|
|
2282
|
+
for (const node of live) {
|
|
2283
|
+
if (!reachable.has(node)) {
|
|
2284
|
+
live.delete(node);
|
|
2285
|
+
changed = true;
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
for (const candidates of candidatesById.values()) {
|
|
2289
|
+
let maxRank = -1;
|
|
2290
|
+
for (const candidate of candidates) {
|
|
2291
|
+
if (live.has(candidate)) maxRank = Math.max(maxRank, rank(candidate));
|
|
2292
|
+
}
|
|
2293
|
+
if (maxRank < 0) continue;
|
|
2294
|
+
for (const candidate of candidates) {
|
|
2295
|
+
if (live.has(candidate) && rank(candidate) < maxRank) {
|
|
2296
|
+
live.delete(candidate);
|
|
2297
|
+
changed = true;
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
if (!changed) break;
|
|
2302
|
+
}
|
|
2055
2303
|
const byId = /* @__PURE__ */ new Map();
|
|
2056
|
-
const
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2304
|
+
const conflictedDefaults = /* @__PURE__ */ new Set();
|
|
2305
|
+
const isOptional = (plugin) => "optional" in plugin && plugin.optional === true;
|
|
2306
|
+
for (const [id, candidates] of candidatesById) {
|
|
2307
|
+
const liveCandidates = candidates.filter(
|
|
2308
|
+
(candidate) => live.has(candidate)
|
|
2309
|
+
);
|
|
2310
|
+
const winner = liveCandidates.find((candidate) => !isOptional(candidate)) ?? liveCandidates[0];
|
|
2311
|
+
if (!winner) continue;
|
|
2312
|
+
if (liveCandidates.length > 1) {
|
|
2313
|
+
const winnerRank = rank(winner);
|
|
2314
|
+
if (winnerRank === 2) {
|
|
2063
2315
|
throw new Error(
|
|
2064
|
-
`createSdk: duplicate plugin id "${
|
|
2316
|
+
`createSdk: duplicate plugin id "${id}". Two different plugins registered under the same id.`
|
|
2065
2317
|
);
|
|
2066
2318
|
}
|
|
2067
|
-
if (
|
|
2068
|
-
|
|
2069
|
-
|
|
2319
|
+
if (winnerRank === 1) {
|
|
2320
|
+
const sources = new Set(
|
|
2321
|
+
liveCandidates.map(
|
|
2322
|
+
(candidate) => candidate.defaultSource
|
|
2323
|
+
)
|
|
2324
|
+
);
|
|
2325
|
+
if (sources.size > 1) conflictedDefaults.add(id);
|
|
2070
2326
|
}
|
|
2071
|
-
return;
|
|
2072
2327
|
}
|
|
2073
|
-
byId.set(
|
|
2074
|
-
|
|
2075
|
-
};
|
|
2076
|
-
visit(root);
|
|
2328
|
+
byId.set(id, winner);
|
|
2329
|
+
}
|
|
2077
2330
|
if (configuration) {
|
|
2078
2331
|
for (const [id, value] of Object.entries(configuration)) {
|
|
2079
2332
|
const existing = byId.get(id);
|
|
@@ -2124,9 +2377,24 @@ function collectPlugins(root, materialized = /* @__PURE__ */ new Set(), configur
|
|
|
2124
2377
|
);
|
|
2125
2378
|
}
|
|
2126
2379
|
}
|
|
2380
|
+
for (const id of conflictedDefaults) {
|
|
2381
|
+
const winner = byId.get(id);
|
|
2382
|
+
if (winner && isDefault(winner)) {
|
|
2383
|
+
throw new Error(
|
|
2384
|
+
`createSdk: conflicting defaults for "${id}". Two different plugins were declared as defaults for the same id and nothing else provides it. Register an explicit (non-default) plugin for this id to choose the winner, or give the implementations distinct ids if they are meant to coexist.`
|
|
2385
|
+
);
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2127
2388
|
return byId;
|
|
2128
2389
|
}
|
|
2129
|
-
function bindValue(
|
|
2390
|
+
function bindValue({
|
|
2391
|
+
target,
|
|
2392
|
+
key,
|
|
2393
|
+
entry,
|
|
2394
|
+
bindMode = "surface",
|
|
2395
|
+
ctx,
|
|
2396
|
+
frameworkOrigin = false
|
|
2397
|
+
}) {
|
|
2130
2398
|
if (entry.pluginType === "property" && entry.getValue) {
|
|
2131
2399
|
Object.defineProperty(target, key, {
|
|
2132
2400
|
get: entry.getValue,
|
|
@@ -2134,7 +2402,7 @@ function bindValue(target, key, entry, callType = "surface", ctx) {
|
|
|
2134
2402
|
configurable: true
|
|
2135
2403
|
});
|
|
2136
2404
|
} else {
|
|
2137
|
-
const value =
|
|
2405
|
+
const value = bindMode === "internal" && entry.pluginType === "method" ? entry.bindInternal?.({ ctx, frameworkOrigin }) ?? entry.internalValue ?? entry.value : entry.value;
|
|
2138
2406
|
Object.defineProperty(target, key, {
|
|
2139
2407
|
value,
|
|
2140
2408
|
writable: true,
|
|
@@ -2152,7 +2420,12 @@ function buildSurface(context, ...maps) {
|
|
|
2152
2420
|
sdk[CONTEXT] = context;
|
|
2153
2421
|
return sdk;
|
|
2154
2422
|
}
|
|
2155
|
-
function buildImports(
|
|
2423
|
+
function buildImports({
|
|
2424
|
+
plugins,
|
|
2425
|
+
importBindings,
|
|
2426
|
+
ctx,
|
|
2427
|
+
frameworkOrigin = false
|
|
2428
|
+
}) {
|
|
2156
2429
|
const imports = {};
|
|
2157
2430
|
for (const { binding, id, optional } of importBindings) {
|
|
2158
2431
|
const entry = plugins[id];
|
|
@@ -2165,10 +2438,31 @@ function buildImports(plugins, importBindings, ctx) {
|
|
|
2165
2438
|
});
|
|
2166
2439
|
continue;
|
|
2167
2440
|
}
|
|
2168
|
-
bindValue(
|
|
2441
|
+
bindValue({
|
|
2442
|
+
target: imports,
|
|
2443
|
+
key: binding,
|
|
2444
|
+
entry,
|
|
2445
|
+
bindMode: "internal",
|
|
2446
|
+
ctx,
|
|
2447
|
+
frameworkOrigin
|
|
2448
|
+
});
|
|
2169
2449
|
}
|
|
2170
2450
|
return imports;
|
|
2171
2451
|
}
|
|
2452
|
+
function bindInternalTwin({
|
|
2453
|
+
ctx,
|
|
2454
|
+
frameworkOrigin,
|
|
2455
|
+
withContext,
|
|
2456
|
+
internalValue
|
|
2457
|
+
}) {
|
|
2458
|
+
if (ctx) {
|
|
2459
|
+
return (...args) => withContext(childCallContext(ctx))(...args);
|
|
2460
|
+
}
|
|
2461
|
+
if (frameworkOrigin) {
|
|
2462
|
+
return (...args) => withContext(rootCallContext({ callOrigin: "internal" }))(...args);
|
|
2463
|
+
}
|
|
2464
|
+
return internalValue;
|
|
2465
|
+
}
|
|
2172
2466
|
function mirrorLegacyRootKeys(context, rootKeys, meta) {
|
|
2173
2467
|
const exports2 = {};
|
|
2174
2468
|
for (const [name, value] of Object.entries(rootKeys)) {
|
|
@@ -2232,7 +2526,11 @@ function bindResolver(resolver, plugins) {
|
|
|
2232
2526
|
case "info":
|
|
2233
2527
|
return { type: "info", text: resolver.text };
|
|
2234
2528
|
case "object": {
|
|
2235
|
-
const imports = buildImports(
|
|
2529
|
+
const imports = buildImports({
|
|
2530
|
+
plugins,
|
|
2531
|
+
importBindings: resolver.importBindings,
|
|
2532
|
+
frameworkOrigin: true
|
|
2533
|
+
});
|
|
2236
2534
|
const bound = {
|
|
2237
2535
|
type: "object",
|
|
2238
2536
|
requireParameters: resolver.requireParameters
|
|
@@ -2273,7 +2571,11 @@ function bindResolver(resolver, plugins) {
|
|
|
2273
2571
|
return bound;
|
|
2274
2572
|
}
|
|
2275
2573
|
case "dynamic": {
|
|
2276
|
-
const imports = buildImports(
|
|
2574
|
+
const imports = buildImports({
|
|
2575
|
+
plugins,
|
|
2576
|
+
importBindings: resolver.importBindings,
|
|
2577
|
+
frameworkOrigin: true
|
|
2578
|
+
});
|
|
2277
2579
|
const {
|
|
2278
2580
|
getContext: getContext2,
|
|
2279
2581
|
listItems,
|
|
@@ -2328,7 +2630,11 @@ function bindDefinitions(definitions, plugins) {
|
|
|
2328
2630
|
return out;
|
|
2329
2631
|
}
|
|
2330
2632
|
function bindFormatter(formatter, plugins) {
|
|
2331
|
-
const imports = buildImports(
|
|
2633
|
+
const imports = buildImports({
|
|
2634
|
+
plugins,
|
|
2635
|
+
importBindings: formatter.importBindings,
|
|
2636
|
+
frameworkOrigin: true
|
|
2637
|
+
});
|
|
2332
2638
|
const bound = { format: formatter.format };
|
|
2333
2639
|
const { getContext: getContext2 } = formatter;
|
|
2334
2640
|
if (getContext2)
|
|
@@ -2402,6 +2708,7 @@ function buildMethodEntries(descriptors, context, states) {
|
|
|
2402
2708
|
const plugins = context.plugins;
|
|
2403
2709
|
for (const [id, descriptor] of descriptors) {
|
|
2404
2710
|
if (descriptor.pluginType !== "method") continue;
|
|
2711
|
+
if (isStandIn(descriptor)) continue;
|
|
2405
2712
|
const out = normalizeOutput(descriptor.output);
|
|
2406
2713
|
const entry = {
|
|
2407
2714
|
pluginType: "method",
|
|
@@ -2416,17 +2723,32 @@ function buildMethodEntries(descriptors, context, states) {
|
|
|
2416
2723
|
// Replaced below; never called.
|
|
2417
2724
|
value: () => void 0
|
|
2418
2725
|
};
|
|
2419
|
-
const callRun = (input, ctx) =>
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2726
|
+
const callRun = (input, ctx) => {
|
|
2727
|
+
const callContext = ctx ?? rootCallContext();
|
|
2728
|
+
return descriptor.run({
|
|
2729
|
+
imports: buildImports({
|
|
2730
|
+
plugins,
|
|
2731
|
+
importBindings: descriptor.importBindings,
|
|
2732
|
+
ctx: callContext
|
|
2733
|
+
}),
|
|
2734
|
+
state: states.get(id),
|
|
2735
|
+
input,
|
|
2736
|
+
callContext,
|
|
2737
|
+
annotate: (metadata) => {
|
|
2738
|
+
Object.assign(callContext.annotations, metadata);
|
|
2739
|
+
}
|
|
2740
|
+
});
|
|
2741
|
+
};
|
|
2424
2742
|
const fold = (coreFn) => (input, ctx) => {
|
|
2425
2743
|
let next = (i) => coreFn(i, ctx);
|
|
2426
2744
|
for (const wrap of entry.chain) {
|
|
2427
2745
|
const inner = next;
|
|
2428
2746
|
next = (i) => wrap.run({
|
|
2429
|
-
imports: buildImports(
|
|
2747
|
+
imports: buildImports({
|
|
2748
|
+
plugins,
|
|
2749
|
+
importBindings: wrap.owner.importBindings,
|
|
2750
|
+
ctx
|
|
2751
|
+
}),
|
|
2430
2752
|
next: inner,
|
|
2431
2753
|
input: i,
|
|
2432
2754
|
// Overwritten by the chain item's own closure with the owning
|
|
@@ -2437,6 +2759,18 @@ function buildMethodEntries(descriptors, context, states) {
|
|
|
2437
2759
|
return next(input);
|
|
2438
2760
|
};
|
|
2439
2761
|
const sdk = { context };
|
|
2762
|
+
const methodAnnotator = descriptor.annotator;
|
|
2763
|
+
const boundAnnotator = methodAnnotator ? (input) => methodAnnotator({ input }) : void 0;
|
|
2764
|
+
const outputPolicy = () => {
|
|
2765
|
+
const core = resolveCoreOptions(context);
|
|
2766
|
+
return {
|
|
2767
|
+
outputSchema: descriptor.meta?.outputSchema,
|
|
2768
|
+
skipOutputValidation: descriptor.skipOutputValidation,
|
|
2769
|
+
includeOutputValidationDroppedPaths: core?.includeOutputValidationDroppedPaths,
|
|
2770
|
+
methodName: descriptor.name,
|
|
2771
|
+
adaptError: core?.adaptError
|
|
2772
|
+
};
|
|
2773
|
+
};
|
|
2440
2774
|
if (out.type === "list") {
|
|
2441
2775
|
entry.value = createPaginatedFunction(
|
|
2442
2776
|
fold(callRun),
|
|
@@ -2446,17 +2780,23 @@ function buildMethodEntries(descriptors, context, states) {
|
|
|
2446
2780
|
name: descriptor.name,
|
|
2447
2781
|
defaultPageSize: out.defaultPageSize,
|
|
2448
2782
|
adaptPage: out.adaptPage,
|
|
2783
|
+
annotator: boundAnnotator,
|
|
2784
|
+
// Validate + strip each item against the item `outputSchema`
|
|
2785
|
+
// (item mode's sibling); dropped paths surface as `[].x` in the page's
|
|
2786
|
+
// `meta`, unioned across items.
|
|
2787
|
+
finalizePage: (page) => applyListOutputPolicy(page, outputPolicy()),
|
|
2449
2788
|
getDeprecation: () => entry.meta?.deprecation
|
|
2450
2789
|
}
|
|
2451
2790
|
);
|
|
2452
2791
|
} else if (out.type === "item") {
|
|
2453
|
-
const itemCore = async (input, ctx) => callRun(input, ctx);
|
|
2792
|
+
const itemCore = async (input, ctx) => applyItemOutputPolicy(await callRun(input, ctx), outputPolicy());
|
|
2454
2793
|
entry.value = createFunction(
|
|
2455
2794
|
fold(itemCore),
|
|
2456
2795
|
{
|
|
2457
2796
|
sdk,
|
|
2458
2797
|
schema: descriptor.inputSchema,
|
|
2459
2798
|
name: descriptor.name,
|
|
2799
|
+
annotator: boundAnnotator,
|
|
2460
2800
|
getDeprecation: () => entry.meta?.deprecation
|
|
2461
2801
|
}
|
|
2462
2802
|
);
|
|
@@ -2468,6 +2808,7 @@ function buildMethodEntries(descriptors, context, states) {
|
|
|
2468
2808
|
name: descriptor.name,
|
|
2469
2809
|
schema: descriptor.skipInputValidation ? void 0 : descriptor.inputSchema,
|
|
2470
2810
|
positional: descriptor.positional,
|
|
2811
|
+
annotator: boundAnnotator,
|
|
2471
2812
|
// The boundary reads the deprecation LIVE off the entry, so a
|
|
2472
2813
|
// deprecation merged after build (defineMethodOverride, addPlugin)
|
|
2473
2814
|
// fires too.
|
|
@@ -2488,12 +2829,22 @@ function buildMethodEntries(descriptors, context, states) {
|
|
|
2488
2829
|
const internalValue = (...args) => canonicalValue(pack(args), INTERNAL_CALL);
|
|
2489
2830
|
entry.value = (...args) => canonicalValue(pack(args));
|
|
2490
2831
|
entry.internalValue = internalValue;
|
|
2491
|
-
entry.bindInternal = (
|
|
2832
|
+
entry.bindInternal = (opts) => bindInternalTwin({
|
|
2833
|
+
...opts,
|
|
2834
|
+
withContext: (context2) => {
|
|
2835
|
+
return (...args) => canonicalValue(pack(args), context2);
|
|
2836
|
+
},
|
|
2837
|
+
internalValue
|
|
2838
|
+
});
|
|
2492
2839
|
entry.positional = names;
|
|
2493
2840
|
} else {
|
|
2494
2841
|
const internalValue = (input) => canonicalValue(input, INTERNAL_CALL);
|
|
2495
2842
|
entry.internalValue = internalValue;
|
|
2496
|
-
entry.bindInternal = (
|
|
2843
|
+
entry.bindInternal = (opts) => bindInternalTwin({
|
|
2844
|
+
...opts,
|
|
2845
|
+
withContext: (context2) => (input) => canonicalValue(input, context2),
|
|
2846
|
+
internalValue
|
|
2847
|
+
});
|
|
2497
2848
|
}
|
|
2498
2849
|
plugins[id] = entry;
|
|
2499
2850
|
}
|
|
@@ -2519,8 +2870,14 @@ function buildEagerArtifacts(descriptors, context, states) {
|
|
|
2519
2870
|
if (!dispose) return;
|
|
2520
2871
|
context.disposers?.push({
|
|
2521
2872
|
id,
|
|
2873
|
+
// Teardown is framework-internal: an SDK method a `dispose` calls runs
|
|
2874
|
+
// on an internal-origin root (dropped from telemetry).
|
|
2522
2875
|
dispose: (input) => dispose({
|
|
2523
|
-
imports: buildImports(
|
|
2876
|
+
imports: buildImports({
|
|
2877
|
+
plugins,
|
|
2878
|
+
importBindings: descriptor.importBindings,
|
|
2879
|
+
frameworkOrigin: true
|
|
2880
|
+
}),
|
|
2524
2881
|
state: states.get(id),
|
|
2525
2882
|
input
|
|
2526
2883
|
})
|
|
@@ -2530,7 +2887,10 @@ function buildEagerArtifacts(descriptors, context, states) {
|
|
|
2530
2887
|
states.set(
|
|
2531
2888
|
id,
|
|
2532
2889
|
descriptor.setup ? descriptor.setup({
|
|
2533
|
-
imports: buildImports(
|
|
2890
|
+
imports: buildImports({
|
|
2891
|
+
plugins,
|
|
2892
|
+
importBindings: descriptor.importBindings
|
|
2893
|
+
})
|
|
2534
2894
|
}) : void 0
|
|
2535
2895
|
);
|
|
2536
2896
|
recordDisposer();
|
|
@@ -2542,14 +2902,20 @@ function buildEagerArtifacts(descriptors, context, states) {
|
|
|
2542
2902
|
states.set(
|
|
2543
2903
|
id,
|
|
2544
2904
|
descriptor.setup ? descriptor.setup({
|
|
2545
|
-
imports: buildImports(
|
|
2905
|
+
imports: buildImports({
|
|
2906
|
+
plugins,
|
|
2907
|
+
importBindings: descriptor.importBindings
|
|
2908
|
+
})
|
|
2546
2909
|
}) : void 0
|
|
2547
2910
|
);
|
|
2548
2911
|
} else {
|
|
2549
2912
|
states.set(
|
|
2550
2913
|
id,
|
|
2551
2914
|
descriptor.setup ? descriptor.setup({
|
|
2552
|
-
imports: buildImports(
|
|
2915
|
+
imports: buildImports({
|
|
2916
|
+
plugins,
|
|
2917
|
+
importBindings: descriptor.importBindings
|
|
2918
|
+
})
|
|
2553
2919
|
}) : void 0
|
|
2554
2920
|
);
|
|
2555
2921
|
if (descriptor.privileged) {
|
|
@@ -2567,7 +2933,7 @@ function buildEagerArtifacts(descriptors, context, states) {
|
|
|
2567
2933
|
pluginType: "property",
|
|
2568
2934
|
name: descriptor.name,
|
|
2569
2935
|
getValue: () => get({
|
|
2570
|
-
imports: buildImports(plugins, importBindings),
|
|
2936
|
+
imports: buildImports({ plugins, importBindings }),
|
|
2571
2937
|
state: states.get(id)
|
|
2572
2938
|
}),
|
|
2573
2939
|
meta: descriptor.meta,
|
|
@@ -2603,7 +2969,7 @@ function resolvePlugin(sdk, ref) {
|
|
|
2603
2969
|
return entry.getValue();
|
|
2604
2970
|
}
|
|
2605
2971
|
if (entry.pluginType === "method" && entry.internalValue) {
|
|
2606
|
-
return entry.internalValue;
|
|
2972
|
+
return entry.bindInternal?.({ frameworkOrigin: true }) ?? entry.internalValue;
|
|
2607
2973
|
}
|
|
2608
2974
|
return entry.value;
|
|
2609
2975
|
}
|
|
@@ -2638,7 +3004,7 @@ function resolveAggregates(descriptors, context) {
|
|
|
2638
3004
|
if (descriptor.pluginType !== "aggregate") continue;
|
|
2639
3005
|
const exports2 = {};
|
|
2640
3006
|
for (const [binding, child] of Object.entries(descriptor.exports)) {
|
|
2641
|
-
bindValue(exports2, binding, plugins[child.id]);
|
|
3007
|
+
bindValue({ target: exports2, key: binding, entry: plugins[child.id] });
|
|
2642
3008
|
}
|
|
2643
3009
|
plugins[id] = { pluginType: "aggregate", name: descriptor.name, exports: exports2 };
|
|
2644
3010
|
}
|
|
@@ -2681,23 +3047,39 @@ function assembleHooks(descriptors, context, states) {
|
|
|
2681
3047
|
const plugins = context.plugins;
|
|
2682
3048
|
for (const id of topoOrder(descriptors)) {
|
|
2683
3049
|
const descriptor = descriptors.get(id);
|
|
2684
|
-
if (!descriptor || descriptor.pluginType !== "hook" || !descriptor.observe) {
|
|
3050
|
+
if (!descriptor || descriptor.pluginType !== "hook" || !descriptor.observe && !descriptor.annotator) {
|
|
2685
3051
|
continue;
|
|
2686
3052
|
}
|
|
2687
|
-
const { observe } = descriptor;
|
|
2688
|
-
const imports = buildImports(plugins, descriptor.importBindings);
|
|
3053
|
+
const { observe, annotator } = descriptor;
|
|
2689
3054
|
const state = states.get(id);
|
|
2690
3055
|
const contributed = {};
|
|
2691
|
-
if (observe
|
|
2692
|
-
const
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
3056
|
+
if (observe?.onMethodStart || observe?.onMethodEnd) {
|
|
3057
|
+
const imports = buildImports({
|
|
3058
|
+
plugins,
|
|
3059
|
+
importBindings: descriptor.importBindings,
|
|
3060
|
+
frameworkOrigin: true
|
|
3061
|
+
});
|
|
3062
|
+
if (observe.onMethodStart) {
|
|
3063
|
+
const onStart = observe.onMethodStart;
|
|
3064
|
+
contributed.onMethodStart = (input) => {
|
|
3065
|
+
runIsolatedObserver(() => onStart({ imports, input, state }));
|
|
3066
|
+
};
|
|
3067
|
+
}
|
|
3068
|
+
if (observe.onMethodEnd) {
|
|
3069
|
+
const onEnd = observe.onMethodEnd;
|
|
3070
|
+
contributed.onMethodEnd = (input) => {
|
|
3071
|
+
runIsolatedObserver(() => onEnd({ imports, input, state }));
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
2696
3074
|
}
|
|
2697
|
-
if (
|
|
2698
|
-
const
|
|
2699
|
-
contributed.
|
|
2700
|
-
|
|
3075
|
+
if (annotator) {
|
|
3076
|
+
const annotatorFn = annotator;
|
|
3077
|
+
contributed.annotator = ({ methodName, input }) => {
|
|
3078
|
+
try {
|
|
3079
|
+
return annotatorFn({ methodName, input, state });
|
|
3080
|
+
} catch {
|
|
3081
|
+
return {};
|
|
3082
|
+
}
|
|
2701
3083
|
};
|
|
2702
3084
|
}
|
|
2703
3085
|
context.hooks = buildHooks(context.hooks, contributed);
|
|
@@ -2731,7 +3113,11 @@ function createSdk(root, options) {
|
|
|
2731
3113
|
pluginSurface = plugins2[plugin.id].exports;
|
|
2732
3114
|
} else {
|
|
2733
3115
|
pluginSurface = {};
|
|
2734
|
-
bindValue(
|
|
3116
|
+
bindValue({
|
|
3117
|
+
target: pluginSurface,
|
|
3118
|
+
key: plugin.name,
|
|
3119
|
+
entry: plugins2[plugin.id]
|
|
3120
|
+
});
|
|
2735
3121
|
}
|
|
2736
3122
|
for (const key of Object.keys(legacyExports)) context.surface[key] = key;
|
|
2737
3123
|
if (plugin.pluginType === "aggregate") {
|
|
@@ -2748,7 +3134,7 @@ function createSdk(root, options) {
|
|
|
2748
3134
|
if (root.pluginType === "method" || root.pluginType === "property") {
|
|
2749
3135
|
context.surface[root.name] = root.id;
|
|
2750
3136
|
const sdk = buildSurface(context);
|
|
2751
|
-
bindValue(sdk, root.name, plugins[root.id]);
|
|
3137
|
+
bindValue({ target: sdk, key: root.name, entry: plugins[root.id] });
|
|
2752
3138
|
return sdk;
|
|
2753
3139
|
}
|
|
2754
3140
|
if (root.pluginType === "aggregate")
|
|
@@ -2780,7 +3166,7 @@ function addModelPlugin(sdk, plugin, options = {}) {
|
|
|
2780
3166
|
context.surface[binding] = child.id;
|
|
2781
3167
|
}
|
|
2782
3168
|
} else {
|
|
2783
|
-
bindValue(sdk, plugin.name, entry);
|
|
3169
|
+
bindValue({ target: sdk, key: plugin.name, entry });
|
|
2784
3170
|
context.surface[plugin.name] = plugin.id;
|
|
2785
3171
|
}
|
|
2786
3172
|
}
|
|
@@ -4120,7 +4506,9 @@ function createCorePlugin(options) {
|
|
|
4120
4506
|
createSdk,
|
|
4121
4507
|
createValidator,
|
|
4122
4508
|
dangerousContextPlugin,
|
|
4509
|
+
declareDefault,
|
|
4123
4510
|
declareMethod,
|
|
4511
|
+
declareOptionalMethod,
|
|
4124
4512
|
declareOptionalProperty,
|
|
4125
4513
|
declarePlugin,
|
|
4126
4514
|
declareProperty,
|