@ekanos/sdk 0.1.2 → 0.1.4
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/README.md +1165 -140
- package/api-report.md +206 -0
- package/dist/components/index.d.ts +3 -2
- package/dist/components/index.js +3 -2
- package/dist/components/index.js.map +1 -1
- package/dist/components/widgets/widget-context.js.map +1 -1
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/index.js.map +1 -1
- package/dist/context/types.d.ts +1 -1
- package/dist/context/types.js.map +1 -1
- package/dist/hooks/activation-actions-context.d.ts +4 -4
- package/dist/hooks/activation-actions-context.js +1 -1
- package/dist/hooks/activation-actions-context.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +2 -2
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-oauth-connection-status.d.ts +18 -72
- package/dist/hooks/use-oauth-connection-status.js +1 -1
- package/dist/hooks/use-oauth-connection-status.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/integration/define-integration.d.ts +2 -3
- package/dist/integration/define-integration.js +2 -3
- package/dist/integration/define-integration.js.map +1 -1
- package/dist/integration/index.d.ts +3 -3
- package/dist/integration/index.js +2 -2
- package/dist/integration/index.js.map +1 -1
- package/dist/integration/types.d.ts +1 -1
- package/dist/integration/types.js.map +1 -1
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/index.js +4 -3
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/invoke.d.ts +25 -1
- package/dist/testing/invoke.js +19 -0
- package/dist/testing/invoke.js.map +1 -1
- package/dist/types/index.d.ts +3 -4
- package/dist/types/index.js +3 -4
- package/dist/types/index.js.map +1 -1
- package/dist/types/integration.d.ts +2 -2
- package/dist/types/integration.js.map +1 -1
- package/dist/types/widget-ask-context.d.ts +1 -1
- package/dist/types/widget-ask-context.js.map +1 -1
- package/eslint.preset.mjs +2 -4
- package/package.json +14 -16
- package/dist/mcp/guards.d.ts +0 -40
- package/dist/mcp/guards.js +0 -99
- package/dist/mcp/guards.js.map +0 -1
- package/dist/mcp/index.d.ts +0 -22
- package/dist/mcp/index.js +0 -22
- package/dist/mcp/index.js.map +0 -1
- package/dist/mcp/ownership.d.ts +0 -74
- package/dist/mcp/ownership.js +0 -83
- package/dist/mcp/ownership.js.map +0 -1
- package/dist/mcp/types.d.ts +0 -145
- package/dist/mcp/types.js +0 -2
- package/dist/mcp/types.js.map +0 -1
|
@@ -42,7 +42,7 @@ export interface UseOAuthConnectionStatusOptions {
|
|
|
42
42
|
export declare function useOAuthConnectionStatus(accountId: string, options: UseOAuthConnectionStatusOptions): {
|
|
43
43
|
oauthJustCompleted: boolean;
|
|
44
44
|
oauthError: string | null;
|
|
45
|
-
data:
|
|
45
|
+
data: {
|
|
46
46
|
isConnected: boolean;
|
|
47
47
|
error: string | undefined;
|
|
48
48
|
obtainedAt?: undefined;
|
|
@@ -50,7 +50,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
50
50
|
isConnected: boolean;
|
|
51
51
|
obtainedAt: string | null | undefined;
|
|
52
52
|
error?: undefined;
|
|
53
|
-
}
|
|
53
|
+
};
|
|
54
54
|
error: Error;
|
|
55
55
|
isError: true;
|
|
56
56
|
isPending: false;
|
|
@@ -73,7 +73,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
73
73
|
isRefetching: boolean;
|
|
74
74
|
isStale: boolean;
|
|
75
75
|
isEnabled: boolean;
|
|
76
|
-
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<
|
|
76
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<{
|
|
77
77
|
isConnected: boolean;
|
|
78
78
|
error: string | undefined;
|
|
79
79
|
obtainedAt?: undefined;
|
|
@@ -81,21 +81,12 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
81
81
|
isConnected: boolean;
|
|
82
82
|
obtainedAt: string | null | undefined;
|
|
83
83
|
error?: undefined;
|
|
84
|
-
}
|
|
84
|
+
}, Error>>;
|
|
85
85
|
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
86
|
-
promise: Promise<NoInfer<{
|
|
87
|
-
isConnected: boolean;
|
|
88
|
-
error: string | undefined;
|
|
89
|
-
obtainedAt?: undefined;
|
|
90
|
-
} | {
|
|
91
|
-
isConnected: boolean;
|
|
92
|
-
obtainedAt: string | null | undefined;
|
|
93
|
-
error?: undefined;
|
|
94
|
-
}>>;
|
|
95
86
|
} | {
|
|
96
87
|
oauthJustCompleted: boolean;
|
|
97
88
|
oauthError: string | null;
|
|
98
|
-
data:
|
|
89
|
+
data: {
|
|
99
90
|
isConnected: boolean;
|
|
100
91
|
error: string | undefined;
|
|
101
92
|
obtainedAt?: undefined;
|
|
@@ -103,7 +94,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
103
94
|
isConnected: boolean;
|
|
104
95
|
obtainedAt: string | null | undefined;
|
|
105
96
|
error?: undefined;
|
|
106
|
-
}
|
|
97
|
+
};
|
|
107
98
|
error: null;
|
|
108
99
|
isError: false;
|
|
109
100
|
isPending: false;
|
|
@@ -126,7 +117,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
126
117
|
isRefetching: boolean;
|
|
127
118
|
isStale: boolean;
|
|
128
119
|
isEnabled: boolean;
|
|
129
|
-
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<
|
|
120
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<{
|
|
130
121
|
isConnected: boolean;
|
|
131
122
|
error: string | undefined;
|
|
132
123
|
obtainedAt?: undefined;
|
|
@@ -134,17 +125,8 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
134
125
|
isConnected: boolean;
|
|
135
126
|
obtainedAt: string | null | undefined;
|
|
136
127
|
error?: undefined;
|
|
137
|
-
}
|
|
128
|
+
}, Error>>;
|
|
138
129
|
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
139
|
-
promise: Promise<NoInfer<{
|
|
140
|
-
isConnected: boolean;
|
|
141
|
-
error: string | undefined;
|
|
142
|
-
obtainedAt?: undefined;
|
|
143
|
-
} | {
|
|
144
|
-
isConnected: boolean;
|
|
145
|
-
obtainedAt: string | null | undefined;
|
|
146
|
-
error?: undefined;
|
|
147
|
-
}>>;
|
|
148
130
|
} | {
|
|
149
131
|
oauthJustCompleted: boolean;
|
|
150
132
|
oauthError: string | null;
|
|
@@ -171,7 +153,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
171
153
|
isRefetching: boolean;
|
|
172
154
|
isStale: boolean;
|
|
173
155
|
isEnabled: boolean;
|
|
174
|
-
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<
|
|
156
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<{
|
|
175
157
|
isConnected: boolean;
|
|
176
158
|
error: string | undefined;
|
|
177
159
|
obtainedAt?: undefined;
|
|
@@ -179,17 +161,8 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
179
161
|
isConnected: boolean;
|
|
180
162
|
obtainedAt: string | null | undefined;
|
|
181
163
|
error?: undefined;
|
|
182
|
-
}
|
|
164
|
+
}, Error>>;
|
|
183
165
|
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
184
|
-
promise: Promise<NoInfer<{
|
|
185
|
-
isConnected: boolean;
|
|
186
|
-
error: string | undefined;
|
|
187
|
-
obtainedAt?: undefined;
|
|
188
|
-
} | {
|
|
189
|
-
isConnected: boolean;
|
|
190
|
-
obtainedAt: string | null | undefined;
|
|
191
|
-
error?: undefined;
|
|
192
|
-
}>>;
|
|
193
166
|
} | {
|
|
194
167
|
oauthJustCompleted: boolean;
|
|
195
168
|
oauthError: string | null;
|
|
@@ -216,7 +189,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
216
189
|
isRefetching: boolean;
|
|
217
190
|
isStale: boolean;
|
|
218
191
|
isEnabled: boolean;
|
|
219
|
-
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<
|
|
192
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<{
|
|
220
193
|
isConnected: boolean;
|
|
221
194
|
error: string | undefined;
|
|
222
195
|
obtainedAt?: undefined;
|
|
@@ -224,17 +197,8 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
224
197
|
isConnected: boolean;
|
|
225
198
|
obtainedAt: string | null | undefined;
|
|
226
199
|
error?: undefined;
|
|
227
|
-
}
|
|
200
|
+
}, Error>>;
|
|
228
201
|
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
229
|
-
promise: Promise<NoInfer<{
|
|
230
|
-
isConnected: boolean;
|
|
231
|
-
error: string | undefined;
|
|
232
|
-
obtainedAt?: undefined;
|
|
233
|
-
} | {
|
|
234
|
-
isConnected: boolean;
|
|
235
|
-
obtainedAt: string | null | undefined;
|
|
236
|
-
error?: undefined;
|
|
237
|
-
}>>;
|
|
238
202
|
} | {
|
|
239
203
|
oauthJustCompleted: boolean;
|
|
240
204
|
oauthError: string | null;
|
|
@@ -261,7 +225,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
261
225
|
isRefetching: boolean;
|
|
262
226
|
isStale: boolean;
|
|
263
227
|
isEnabled: boolean;
|
|
264
|
-
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<
|
|
228
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<{
|
|
265
229
|
isConnected: boolean;
|
|
266
230
|
error: string | undefined;
|
|
267
231
|
obtainedAt?: undefined;
|
|
@@ -269,21 +233,12 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
269
233
|
isConnected: boolean;
|
|
270
234
|
obtainedAt: string | null | undefined;
|
|
271
235
|
error?: undefined;
|
|
272
|
-
}
|
|
236
|
+
}, Error>>;
|
|
273
237
|
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
274
|
-
promise: Promise<NoInfer<{
|
|
275
|
-
isConnected: boolean;
|
|
276
|
-
error: string | undefined;
|
|
277
|
-
obtainedAt?: undefined;
|
|
278
|
-
} | {
|
|
279
|
-
isConnected: boolean;
|
|
280
|
-
obtainedAt: string | null | undefined;
|
|
281
|
-
error?: undefined;
|
|
282
|
-
}>>;
|
|
283
238
|
} | {
|
|
284
239
|
oauthJustCompleted: boolean;
|
|
285
240
|
oauthError: string | null;
|
|
286
|
-
data:
|
|
241
|
+
data: {
|
|
287
242
|
isConnected: boolean;
|
|
288
243
|
error: string | undefined;
|
|
289
244
|
obtainedAt?: undefined;
|
|
@@ -291,7 +246,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
291
246
|
isConnected: boolean;
|
|
292
247
|
obtainedAt: string | null | undefined;
|
|
293
248
|
error?: undefined;
|
|
294
|
-
}
|
|
249
|
+
};
|
|
295
250
|
isError: false;
|
|
296
251
|
error: null;
|
|
297
252
|
isPending: false;
|
|
@@ -314,7 +269,7 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
314
269
|
isRefetching: boolean;
|
|
315
270
|
isStale: boolean;
|
|
316
271
|
isEnabled: boolean;
|
|
317
|
-
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<
|
|
272
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<{
|
|
318
273
|
isConnected: boolean;
|
|
319
274
|
error: string | undefined;
|
|
320
275
|
obtainedAt?: undefined;
|
|
@@ -322,17 +277,8 @@ export declare function useOAuthConnectionStatus(accountId: string, options: Use
|
|
|
322
277
|
isConnected: boolean;
|
|
323
278
|
obtainedAt: string | null | undefined;
|
|
324
279
|
error?: undefined;
|
|
325
|
-
}
|
|
280
|
+
}, Error>>;
|
|
326
281
|
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
327
|
-
promise: Promise<NoInfer<{
|
|
328
|
-
isConnected: boolean;
|
|
329
|
-
error: string | undefined;
|
|
330
|
-
obtainedAt?: undefined;
|
|
331
|
-
} | {
|
|
332
|
-
isConnected: boolean;
|
|
333
|
-
obtainedAt: string | null | undefined;
|
|
334
|
-
error?: undefined;
|
|
335
|
-
}>>;
|
|
336
282
|
};
|
|
337
283
|
/**
|
|
338
284
|
* Resolves the gating booleans every OAuth-backed dashboard widget needs:
|
|
@@ -42,7 +42,7 @@ export function useOAuthConnectionStatus(accountId, options) {
|
|
|
42
42
|
refetchOnWindowFocus: false,
|
|
43
43
|
});
|
|
44
44
|
const errorParamName = errorParam === null || errorParam === void 0 ? void 0 : errorParam.name;
|
|
45
|
-
// Justified useEffect
|
|
45
|
+
// Justified useEffect: after the OAuth redirect lands back
|
|
46
46
|
// on this page with `?oauth_success=true`, we must (1) strip the transient
|
|
47
47
|
// query params from the URL and (2) invalidate the cached connection status
|
|
48
48
|
// so widgets flip to connected without a manual refresh. Both are
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-oauth-connection-status.js","sourceRoot":"","sources":["../../src/hooks/use-oauth-connection-status.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAuCjE;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,SAAiB,EACjB,OAAwC;IAExC,MAAM,EACJ,aAAa,EACb,eAAe,EACf,OAAO,GAAG,IAAI,EACd,UAAU,GACX,GAAG,OAAO,CAAC;IACZ,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,CAAC,kBAAkB,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;QACzC,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3D,OAAO,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,MAAM,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAgB,GAAG,EAAE;QAChD,IAAI,CAAC,UAAU,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9D,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAC3D,UAAU,CAAC,IAAI,CAChB,CAAC;QACF,OAAO,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,QAAQ,CAAC;QACrB,QAAQ,EAAE,CAAC,kBAAkB,EAAE,SAAS,EAAE,aAAa,CAAC;QACxD,OAAO,EAAE,KAAK,IAAI,EAAE;;YAClB,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;YAEpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;YACrD,CAAC;YAED,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,UAAU,EAAE,MAAA,MAAM,CAAC,IAAI,0CAAE,UAAU;aACpC,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,IAAI,CAAC,CAAC,SAAS;QAC/B,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;QACxB,oBAAoB,EAAE,KAAK;KAC5B,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,IAAI,CAAC;IAExC,
|
|
1
|
+
{"version":3,"file":"use-oauth-connection-status.js","sourceRoot":"","sources":["../../src/hooks/use-oauth-connection-status.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAuCjE;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,SAAiB,EACjB,OAAwC;IAExC,MAAM,EACJ,aAAa,EACb,eAAe,EACf,OAAO,GAAG,IAAI,EACd,UAAU,GACX,GAAG,OAAO,CAAC;IACZ,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,CAAC,kBAAkB,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;QACzC,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3D,OAAO,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,MAAM,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAgB,GAAG,EAAE;QAChD,IAAI,CAAC,UAAU,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9D,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAC3D,UAAU,CAAC,IAAI,CAChB,CAAC;QACF,OAAO,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,QAAQ,CAAC;QACrB,QAAQ,EAAE,CAAC,kBAAkB,EAAE,SAAS,EAAE,aAAa,CAAC;QACxD,OAAO,EAAE,KAAK,IAAI,EAAE;;YAClB,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;YAEpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;YACrD,CAAC;YAED,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,UAAU,EAAE,MAAA,MAAM,CAAC,IAAI,0CAAE,UAAU;aACpC,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,IAAI,CAAC,CAAC,SAAS;QAC/B,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;QACxB,oBAAoB,EAAE,KAAK;KAC5B,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,IAAI,CAAC;IAExC,2DAA2D;IAC3D,2EAA2E;IAC3E,4EAA4E;IAC5E,kEAAkE;IAClE,oEAAoE;IACpE,uCAAuC;IACvC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,kBAAkB;YAAE,OAAO;QAEhC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1C,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAEzC,IAAI,cAAc,EAAE,CAAC;YACnB,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QAE/D,WAAW,CAAC,iBAAiB,CAAC;YAC5B,QAAQ,EAAE,CAAC,kBAAkB,EAAE,SAAS,EAAE,aAAa,CAAC;SACzD,CAAC,CAAC;IACL,CAAC,EAAE;QACD,kBAAkB;QAClB,SAAS;QACT,aAAa;QACb,cAAc;QACd,WAAW;KACZ,CAAC,CAAC;IAEH,uCAAY,KAAK,KAAE,kBAAkB,EAAE,UAAU,IAAG;AACtD,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAA6B,EAC7B,iBAA0B,EAC1B,OAGC;;IAED,MAAM,OAAO,GAAG,iBAAiB,IAAI,CAAC,CAAC,SAAS,CAAC;IACjD,MAAM,KAAK,GAAG,wBAAwB,CAAC,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,EAAE,kCACjD,OAAO,KACV,OAAO,IACP,CAAC;IAEH,MAAM,iBAAiB,GAAG,OAAO,IAAI,KAAK,CAAC,SAAS,CAAC;IACrD,MAAM,eAAe,GAAG,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;IACjD,MAAM,WAAW,GAAG,CAAA,MAAA,KAAK,CAAC,IAAI,0CAAE,WAAW,MAAK,IAAI,CAAC;IACrD,MAAM,WAAW,GAAG,OAAO,IAAI,WAAW,CAAC;IAC3C,0EAA0E;IAC1E,0EAA0E;IAC1E,MAAM,YAAY,GAChB,OAAO,IAAI,CAAC,iBAAiB,IAAI,CAAC,eAAe,IAAI,CAAC,WAAW,CAAC;IAEpE,OAAO;QACL,OAAO;QACP,WAAW;QACX,iBAAiB;QACjB,eAAe;QACf,WAAW;QACX,YAAY;KACb,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\nimport { useQuery, useQueryClient } from '@tanstack/react-query';\n\n/**\n * Result shape of an integration's check-connection server action\n * (the standard enhanceAction envelope).\n */\nexport interface ConnectionCheckResult {\n success: boolean;\n data?: { obtainedAt?: string | null } | null;\n error?: string;\n}\n\nexport type ConnectionCheckAction = (input: {\n accountId: string;\n}) => Promise<ConnectionCheckResult>;\n\n/**\n * Optional OAuth failure query param an integration's connect route may\n * append on redirect (e.g. dropbox_error=credentials_not_configured).\n */\nexport interface OAuthErrorParam {\n name: string;\n /** Map the raw param value to a user-facing message; return null to ignore. */\n toMessage: (value: string) => string | null;\n}\n\nexport interface UseOAuthConnectionStatusOptions {\n /**\n * Cache key segment, by convention `<slug>-connection`. The full query key\n * is ['integration-data', accountId, connectionKey] so all widgets and the\n * activation form share one deduped request per dashboard load.\n */\n connectionKey: string;\n checkConnection: ConnectionCheckAction;\n /** Gate the query (e.g. on integration-active state). Defaults to true. */\n enabled?: boolean;\n errorParam?: OAuthErrorParam;\n}\n\n/**\n * Shared OAuth connection-status hook. Detects the `oauth_success=true`\n * return from an integration's connect route, strips the transient params\n * from the URL, and invalidates the cached status so dependent UI flips to\n * connected without a manual refresh.\n */\nexport function useOAuthConnectionStatus(\n accountId: string,\n options: UseOAuthConnectionStatusOptions,\n) {\n const {\n connectionKey,\n checkConnection,\n enabled = true,\n errorParam,\n } = options;\n const queryClient = useQueryClient();\n\n // Read the OAuth return params synchronously on mount (not in an effect)\n // so the first render already knows whether we just came back from OAuth.\n const [oauthJustCompleted] = useState(() => {\n if (typeof window === 'undefined') return false;\n const params = new URLSearchParams(window.location.search);\n return params.get('oauth_success') === 'true';\n });\n\n const [oauthError] = useState<string | null>(() => {\n if (!errorParam || typeof window === 'undefined') return null;\n const value = new URLSearchParams(window.location.search).get(\n errorParam.name,\n );\n return value ? errorParam.toMessage(value) : null;\n });\n\n const query = useQuery({\n queryKey: ['integration-data', accountId, connectionKey],\n queryFn: async () => {\n const result = await checkConnection({ accountId });\n\n if (!result.success) {\n return { isConnected: false, error: result.error };\n }\n\n return {\n isConnected: true,\n obtainedAt: result.data?.obtainedAt,\n };\n },\n enabled: enabled && !!accountId,\n staleTime: 5 * 60 * 1000,\n refetchOnWindowFocus: false,\n });\n\n const errorParamName = errorParam?.name;\n\n // Justified useEffect: after the OAuth redirect lands back\n // on this page with `?oauth_success=true`, we must (1) strip the transient\n // query params from the URL and (2) invalidate the cached connection status\n // so widgets flip to connected without a manual refresh. Both are\n // post-render side effects on external systems (history API + query\n // cache), not derivable during render.\n useEffect(() => {\n if (!oauthJustCompleted) return;\n\n const url = new URL(window.location.href);\n url.searchParams.delete('oauth_success');\n\n if (errorParamName) {\n url.searchParams.delete(errorParamName);\n }\n\n window.history.replaceState({}, '', url.pathname + url.search);\n\n queryClient.invalidateQueries({\n queryKey: ['integration-data', accountId, connectionKey],\n });\n }, [\n oauthJustCompleted,\n accountId,\n connectionKey,\n errorParamName,\n queryClient,\n ]);\n\n return { ...query, oauthJustCompleted, oauthError };\n}\n\n/**\n * Resolves the gating booleans every OAuth-backed dashboard widget needs:\n *\n * - `enabled` — the integration is active and an account id is present.\n * - `isConnected` — a live OAuth connection exists (access token).\n * - `dataEnabled` — safe to fire the widget's data query (active + connected).\n * - `connectionPending` — still resolving the connection status.\n * - `connectionError` — the connection check itself failed (network/5xx).\n * Distinct from `notConnected`: a transient failure should surface as an\n * error, not as a misleading \"connect X\" prompt.\n * - `notConnected` — activated, resolved without error, but no OAuth\n * connection. The widget should render its \"connect X\" inactive state.\n *\n * The underlying connection check shares one query key across all widgets,\n * so react-query dedupes it to a single request per dashboard load.\n */\nexport function useOAuthWidgetGate(\n accountId: string | undefined,\n integrationActive: boolean,\n options: Pick<\n UseOAuthConnectionStatusOptions,\n 'connectionKey' | 'checkConnection'\n >,\n) {\n const enabled = integrationActive && !!accountId;\n const query = useOAuthConnectionStatus(accountId ?? '', {\n ...options,\n enabled,\n });\n\n const connectionPending = enabled && query.isPending;\n const connectionError = enabled && query.isError;\n const isConnected = query.data?.isConnected === true;\n const dataEnabled = enabled && isConnected;\n // Only treat as \"not connected\" when the check resolved successfully with\n // no token — a query error is an error state, not a disconnected account.\n const notConnected =\n enabled && !connectionPending && !connectionError && !isConnected;\n\n return {\n enabled,\n isConnected,\n connectionPending,\n connectionError,\n dataEnabled,\n notConnected,\n };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
*
|
|
9
9
|
* The SDK OWNS these definitions (`./types` — nothing imported from `@kit/*`);
|
|
10
10
|
* `@kit/integrations-core` keeps copies of some for now, and the parity guard
|
|
11
|
-
* (
|
|
11
|
+
* (a host-side parity test asserts it —
|
|
12
12
|
* core-side since the inversion, because the dependency arrow is core → SDK)
|
|
13
13
|
* fails core's typecheck on any drift.
|
|
14
14
|
*
|
|
15
15
|
* Surface discipline: additions require a second consumer and a line in
|
|
16
|
-
*
|
|
16
|
+
* api-report.md, the checked-in snapshot of every entrypoint's exports.
|
|
17
|
+
* Keep the whole surface readable in one pass.
|
|
17
18
|
*/
|
|
18
19
|
export type { IntegrationMetadata, IntegrationCapability, IntegrationPermission, IntegrationConfig, IntegrationComponentProps, ActivationFormProps, ActivationResult, MarketplaceTileProps, WidgetConfig, WorkspaceTargetDefinition, WidgetAskContext, WidgetSnapshot, WidgetSuggestedPrompt, HealthCheckResult, HealthStatus, AccountProductData, AccountProductDataType, } from './types/index.js';
|
|
19
20
|
export type { IntegrationContext, IntegrationActor, IntegrationStorage, ScopedStore, IntegrationSecrets, IntegrationFetch, IntegrationLogger, StorageEntry, StorageWriteOptions, StorageSchemas, StorageSchemaMap, StorageScopeSchemas, StorageKeyDeclaration, StorageKeyDeclarationInput, StorageKeySchema, } from './context/types.js';
|
package/dist/index.js
CHANGED
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
*
|
|
9
9
|
* The SDK OWNS these definitions (`./types` — nothing imported from `@kit/*`);
|
|
10
10
|
* `@kit/integrations-core` keeps copies of some for now, and the parity guard
|
|
11
|
-
* (
|
|
11
|
+
* (a host-side parity test asserts it —
|
|
12
12
|
* core-side since the inversion, because the dependency arrow is core → SDK)
|
|
13
13
|
* fails core's typecheck on any drift.
|
|
14
14
|
*
|
|
15
15
|
* Surface discipline: additions require a second consumer and a line in
|
|
16
|
-
*
|
|
16
|
+
* api-report.md, the checked-in snapshot of every entrypoint's exports.
|
|
17
|
+
* Keep the whole surface readable in one pass.
|
|
17
18
|
*/
|
|
18
19
|
export {};
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG","sourcesContent":["/**\n * @ekanos/sdk — the integration contract.\n *\n * Types only. This entrypoint is importable from any module, client or\n * server, and must stay that way: every export below is a `type` re-export,\n * so nothing here can pull runtime code into a client bundle. Runtime lives\n * in `@ekanos/sdk/components`, `@ekanos/sdk/hooks`, and `@ekanos/sdk/mcp`.\n *\n * The SDK OWNS these definitions (`./types` — nothing imported from `@kit/*`);\n * `@kit/integrations-core` keeps copies of some for now, and the parity guard\n * (a host-side parity test asserts it —\n * core-side since the inversion, because the dependency arrow is core → SDK)\n * fails core's typecheck on any drift.\n *\n * Surface discipline: additions require a second consumer and a line in\n * api-report.md, the checked-in snapshot of every entrypoint's exports.\n * Keep the whole surface readable in one pass.\n */\n\nexport type {\n // The integration definition\n IntegrationMetadata,\n IntegrationCapability,\n IntegrationPermission,\n IntegrationConfig,\n\n // Component contracts\n IntegrationComponentProps,\n ActivationFormProps,\n ActivationResult,\n MarketplaceTileProps,\n WidgetConfig,\n WorkspaceTargetDefinition,\n\n // AI ask-footer contract\n WidgetAskContext,\n WidgetSnapshot,\n WidgetSuggestedPrompt,\n\n // Health contract (required to implement checkHealth)\n HealthCheckResult,\n HealthStatus,\n\n // Account-scoped data seam\n AccountProductData,\n AccountProductDataType,\n} from './types';\n\nexport type {\n // The capability context — the one object partner code receives;\n // handed to MCP tool run() and server handlers; the mock lives in\n // @ekanos/sdk/testing, the shared runtime values in @ekanos/sdk/context.\n IntegrationContext,\n IntegrationActor,\n IntegrationStorage,\n ScopedStore,\n IntegrationSecrets,\n IntegrationFetch,\n IntegrationLogger,\n StorageEntry,\n StorageWriteOptions,\n\n // Storage schema declaration (ruling 1) — consumed by defineIntegration()\n // and createMockContext()\n StorageSchemas,\n StorageSchemaMap,\n StorageScopeSchemas,\n\n // Per-key declaration form carrying exposure flags. `clientReadable`\n // (default false) is what opts a key in to the generic browser-readable\n // storage route — see StorageKeyDeclaration for the full rationale.\n StorageKeyDeclaration,\n StorageKeyDeclarationInput,\n StorageKeySchema,\n} from './context/types';\n"]}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `defineIntegration()` — the v1 partner authoring contract
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* the host adapts it internally).
|
|
3
|
+
* Partners never extend a base class: they hand the host a validated, frozen
|
|
4
|
+
* definition and the host adapts it internally.
|
|
6
5
|
*
|
|
7
6
|
* The validation logic and the schema itself live in the dependency-pure
|
|
8
7
|
* `@ekanos/integration-schema` (F3/F9): `defineIntegration()` validates at
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `defineIntegration()` — the v1 partner authoring contract
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* the host adapts it internally).
|
|
3
|
+
* Partners never extend a base class: they hand the host a validated, frozen
|
|
4
|
+
* definition and the host adapts it internally.
|
|
6
5
|
*
|
|
7
6
|
* The validation logic and the schema itself live in the dependency-pure
|
|
8
7
|
* `@ekanos/integration-schema` (F3/F9): `defineIntegration()` validates at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-integration.js","sourceRoot":"","sources":["../../src/integration/define-integration.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"define-integration.js","sourceRoot":"","sources":["../../src/integration/define-integration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAGL,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAE5D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAE/B,UAA0C;IAC1C,4EAA4E;IAC5E,yEAAyE;IACzE,uEAAuE;IACvE,6BAA6B;IAC7B,MAAM,MAAM,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAEtD,wEAAwE;IACxE,4EAA4E;IAC5E,uCAAuC;IACvC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAEjC,OAAO,MAAmD,CAAC;AAC7D,CAAC","sourcesContent":["/**\n * `defineIntegration()` — the v1 partner authoring contract\n * Partners never extend a base class: they hand the host a validated, frozen\n * definition and the host adapts it internally.\n *\n * The validation logic and the schema itself live in the dependency-pure\n * `@ekanos/integration-schema` (F3/F9): `defineIntegration()` validates at\n * authoring time and `registerPartnerIntegration()` re-validates against the\n * SAME schema at the host trust boundary, so there is one contract with no\n * hand-written twin. This function adds only the generic authoring type;\n * `IntegrationDefinitionSchema` is re-exported for the promote gate and\n * dev-mcp validators.\n */\nimport {\n type IntegrationDefinition,\n type StorageSchemas,\n parseIntegrationDefinition,\n} from '@ekanos/integration-schema';\n\nimport { assertEventSurfacesValid } from './event-surfaces';\n\n/**\n * Validates a partner integration definition and returns it deep-frozen.\n *\n * `parseIntegrationDefinition` performs the validation AND the deep-freeze\n * (F4: the canonical parser freezes so both this and\n * `registerPartnerIntegration()` return immutable output). Throws with a\n * remediation-instruction message on invalid input. The declared `Schemas`\n * generic threads through to `ctx.storage` typing in each tool's `run`\n * handler and is preserved by `registerPartnerIntegration()`.\n * Cross-DEFINITION collisions (two packages, one slug) are\n * `validateIntegrationDefinitions()`'s job.\n */\nexport function defineIntegration<\n Schemas extends StorageSchemas = StorageSchemas,\n>(definition: IntegrationDefinition<Schemas>): IntegrationDefinition<Schemas> {\n // parseIntegrationDefinition returns the loose (default-generic) shape; the\n // storage/tool generic cannot be recovered from a runtime parse, but the\n // parsed value IS the same definition, so re-narrowing to the caller's\n // declared Schemas is sound.\n const parsed = parseIntegrationDefinition(definition);\n\n // SDK-layer event-surface rules the zod-only schema package cannot own:\n // 5-field cron syntax on every schedule, and OAuth endpoint origins covered\n // by the definition's own egress list.\n assertEventSurfacesValid(parsed);\n\n return parsed as unknown as IntegrationDefinition<Schemas>;\n}\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @ekanos/sdk/integration — the partner authoring contract.
|
|
3
3
|
*
|
|
4
4
|
* `defineIntegration()` is THE way a partner declares an integration
|
|
5
|
-
*
|
|
5
|
+
* Partners never extend a base class.
|
|
6
6
|
* The host adapts the returned definition internally via
|
|
7
7
|
* `registerPartnerIntegration` in `@kit/integrations-core`, which re-parses
|
|
8
8
|
* against the SAME canonical schema (`@ekanos/integration-schema`) at the
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
* no `server-only`.
|
|
13
13
|
*
|
|
14
14
|
* Surface discipline: additions require an entry in
|
|
15
|
-
*
|
|
15
|
+
* api-report.md, regenerated by `pnpm --filter @ekanos/sdk api-report`.
|
|
16
16
|
*/
|
|
17
17
|
export { defineIntegration } from './define-integration.js';
|
|
18
18
|
export { parseCronExpression } from './cron.js';
|
|
19
19
|
export { IntegrationDefinitionSchema, validateIntegrationDefinitions, } from '@ekanos/integration-schema';
|
|
20
|
-
export type { IntegrationDefinition, IntegrationComponentDeclarations, IntegrationProposals, IntegrationCapabilityDeclaration, IntegrationPermissionDeclaration, PartnerWidgetDeclaration, PartnerToolModule, PartnerToolParameters, ToolClassificationProposal, DefinitionCollisionInput, FirstPartyInventory, PartnerWebhookDeclaration, WebhookSignatureDeclaration, WebhookEvent, WebhookResult, PartnerScheduleDeclaration, ScheduleInvocation, ScheduleResult, PartnerOAuthDeclaration, OAuthProviderDeclaration, OAuthTokens, } from '@ekanos/integration-schema';
|
|
20
|
+
export type { IntegrationDefinition, IntegrationComponentDeclarations, IntegrationProposals, IntegrationCapabilityDeclaration, IntegrationPermissionDeclaration, PartnerWidgetDeclaration, PartnerToolModule, PartnerToolParameters, ToolClassificationProposal, DefinitionCollisionInput, FirstPartyInventory, PartnerWebhookDeclaration, WebhookSignatureDeclaration, WebhookEvent, WebhookResult, PartnerScheduleDeclaration, ScheduleInvocation, ScheduleResult, PartnerOAuthDeclaration, OAuthProviderDeclaration, OAuthTokens, OnActivateHandler, } from '@ekanos/integration-schema';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @ekanos/sdk/integration — the partner authoring contract.
|
|
3
3
|
*
|
|
4
4
|
* `defineIntegration()` is THE way a partner declares an integration
|
|
5
|
-
*
|
|
5
|
+
* Partners never extend a base class.
|
|
6
6
|
* The host adapts the returned definition internally via
|
|
7
7
|
* `registerPartnerIntegration` in `@kit/integrations-core`, which re-parses
|
|
8
8
|
* against the SAME canonical schema (`@ekanos/integration-schema`) at the
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* no `server-only`.
|
|
13
13
|
*
|
|
14
14
|
* Surface discipline: additions require an entry in
|
|
15
|
-
*
|
|
15
|
+
* api-report.md, regenerated by `pnpm --filter @ekanos/sdk api-report`.
|
|
16
16
|
*/
|
|
17
17
|
export { defineIntegration } from './define-integration.js';
|
|
18
18
|
// Event-surface validation values: the 5-field cron parser backing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integration/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,mEAAmE;AACnE,0EAA0E;AAC1E,0EAA0E;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,4BAA4B,CAAC","sourcesContent":["/**\n * @ekanos/sdk/integration — the partner authoring contract.\n *\n * `defineIntegration()` is THE way a partner declares an integration\n *
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/integration/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,mEAAmE;AACnE,0EAA0E;AAC1E,0EAA0E;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,4BAA4B,CAAC","sourcesContent":["/**\n * @ekanos/sdk/integration — the partner authoring contract.\n *\n * `defineIntegration()` is THE way a partner declares an integration\n * Partners never extend a base class.\n * The host adapts the returned definition internally via\n * `registerPartnerIntegration` in `@kit/integrations-core`, which re-parses\n * against the SAME canonical schema (`@ekanos/integration-schema`) at the\n * trust boundary — one contract, no structural twin (F3/F9).\n *\n * Dependency-pure and isomorphic: zod plus the schema package, no `@kit/*`,\n * no `server-only`.\n *\n * Surface discipline: additions require an entry in\n * api-report.md, regenerated by `pnpm --filter @ekanos/sdk api-report`.\n */\n\nexport { defineIntegration } from './define-integration';\n\n// Event-surface validation values: the 5-field cron parser backing\n// `defineIntegration()`'s schedule validation, exported so validators and\n// the harness can check/describe an expression the same way the SDK does.\nexport { parseCronExpression } from './cron';\n\nexport {\n IntegrationDefinitionSchema,\n validateIntegrationDefinitions,\n} from '@ekanos/integration-schema';\n\nexport type {\n IntegrationDefinition,\n IntegrationComponentDeclarations,\n IntegrationProposals,\n IntegrationCapabilityDeclaration,\n IntegrationPermissionDeclaration,\n PartnerWidgetDeclaration,\n PartnerToolModule,\n PartnerToolParameters,\n ToolClassificationProposal,\n DefinitionCollisionInput,\n FirstPartyInventory,\n // Event surfaces (webhooks, schedules, OAuth): declared in the definition,\n // executed locally by the harness/testing helpers today; the host's real\n // transports (public ingress, scheduler, hosted OAuth callback) bind to\n // these exact declarations later with no partner code change.\n PartnerWebhookDeclaration,\n WebhookSignatureDeclaration,\n WebhookEvent,\n WebhookResult,\n PartnerScheduleDeclaration,\n ScheduleInvocation,\n ScheduleResult,\n PartnerOAuthDeclaration,\n OAuthProviderDeclaration,\n OAuthTokens,\n // Activation lifecycle hook: cache seeding / eager validation at connect\n // time. Runs after first persist and after every activationData update;\n // v1 errors are non-fatal (logged as a warning, activation stays active).\n OnActivateHandler,\n} from '@ekanos/integration-schema';\n"]}
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* one contract and no structural twin — F9). This file re-exports them under
|
|
5
5
|
* `@ekanos/sdk/integration`.
|
|
6
6
|
*/
|
|
7
|
-
export type { IntegrationDefinition, IntegrationComponentDeclarations, IntegrationProposals, IntegrationCapabilityDeclaration, IntegrationPermissionDeclaration, PartnerWidgetDeclaration, PartnerToolModule, PartnerToolParameters, ToolClassificationProposal, PartnerWebhookDeclaration, WebhookSignatureDeclaration, WebhookEvent, WebhookResult, PartnerScheduleDeclaration, ScheduleInvocation, ScheduleResult, PartnerOAuthDeclaration, OAuthProviderDeclaration, OAuthTokens, } from '@ekanos/integration-schema';
|
|
7
|
+
export type { IntegrationDefinition, IntegrationComponentDeclarations, IntegrationProposals, IntegrationCapabilityDeclaration, IntegrationPermissionDeclaration, PartnerWidgetDeclaration, PartnerToolModule, PartnerToolParameters, ToolClassificationProposal, PartnerWebhookDeclaration, WebhookSignatureDeclaration, WebhookEvent, WebhookResult, PartnerScheduleDeclaration, ScheduleInvocation, ScheduleResult, PartnerOAuthDeclaration, OAuthProviderDeclaration, OAuthTokens, OnActivateHandler, } from '@ekanos/integration-schema';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/integration/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * The partner authoring types are owned by `@ekanos/integration-schema` (the\n * dependency-pure package `@kit/integrations-core` also imports, so there is\n * one contract and no structural twin — F9). This file re-exports them under\n * `@ekanos/sdk/integration`.\n */\nexport type {\n IntegrationDefinition,\n IntegrationComponentDeclarations,\n IntegrationProposals,\n IntegrationCapabilityDeclaration,\n IntegrationPermissionDeclaration,\n PartnerWidgetDeclaration,\n PartnerToolModule,\n PartnerToolParameters,\n ToolClassificationProposal,\n PartnerWebhookDeclaration,\n WebhookSignatureDeclaration,\n WebhookEvent,\n WebhookResult,\n PartnerScheduleDeclaration,\n ScheduleInvocation,\n ScheduleResult,\n PartnerOAuthDeclaration,\n OAuthProviderDeclaration,\n OAuthTokens,\n} from '@ekanos/integration-schema';\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/integration/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * The partner authoring types are owned by `@ekanos/integration-schema` (the\n * dependency-pure package `@kit/integrations-core` also imports, so there is\n * one contract and no structural twin — F9). This file re-exports them under\n * `@ekanos/sdk/integration`.\n */\nexport type {\n IntegrationDefinition,\n IntegrationComponentDeclarations,\n IntegrationProposals,\n IntegrationCapabilityDeclaration,\n IntegrationPermissionDeclaration,\n PartnerWidgetDeclaration,\n PartnerToolModule,\n PartnerToolParameters,\n ToolClassificationProposal,\n PartnerWebhookDeclaration,\n WebhookSignatureDeclaration,\n WebhookEvent,\n WebhookResult,\n PartnerScheduleDeclaration,\n ScheduleInvocation,\n ScheduleResult,\n PartnerOAuthDeclaration,\n OAuthProviderDeclaration,\n OAuthTokens,\n OnActivateHandler,\n} from '@ekanos/integration-schema';\n"]}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* shared implementation from `@ekanos/sdk/context` that production uses.
|
|
9
9
|
*
|
|
10
10
|
* Surface discipline: additions require an entry in
|
|
11
|
-
*
|
|
11
|
+
* api-report.md, regenerated by `pnpm --filter @ekanos/sdk api-report`.
|
|
12
12
|
*/
|
|
13
13
|
export { createMockContext } from './mock-context.js';
|
|
14
14
|
export type { MockContextOptions, MockFetchHandler, MockIntegrationContext, RecordedFetchCall, RecordedLog, } from './mock-context.js';
|
|
15
|
-
export { invokeWebhook, invokeSchedule } from './invoke.js';
|
|
16
|
-
export type { DefinitionContextOptions, InvokeWebhookOptions, InvokeScheduleOptions, WebhookInvocationOutcome, ScheduleInvocationOutcome, } from './invoke.js';
|
|
15
|
+
export { invokeWebhook, invokeSchedule, invokeActivate } from './invoke.js';
|
|
16
|
+
export type { DefinitionContextOptions, InvokeWebhookOptions, InvokeScheduleOptions, InvokeActivateOptions, WebhookInvocationOutcome, ScheduleInvocationOutcome, ActivateInvocationOutcome, } from './invoke.js';
|
package/dist/testing/index.js
CHANGED
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
* shared implementation from `@ekanos/sdk/context` that production uses.
|
|
9
9
|
*
|
|
10
10
|
* Surface discipline: additions require an entry in
|
|
11
|
-
*
|
|
11
|
+
* api-report.md, regenerated by `pnpm --filter @ekanos/sdk api-report`.
|
|
12
12
|
*/
|
|
13
13
|
export { createMockContext } from './mock-context.js';
|
|
14
14
|
// Event-surface invocation: run declared webhook/schedule handlers locally,
|
|
15
15
|
// with the same payload-validation and context-derivation semantics the real
|
|
16
16
|
// transports will have. Used by partner unit tests and the harness Triggers
|
|
17
|
-
// panel alike.
|
|
18
|
-
|
|
17
|
+
// panel alike. `invokeActivate` does the same for the `onActivate` lifecycle
|
|
18
|
+
// hook, used by partner unit tests and the harness's activation surface.
|
|
19
|
+
export { invokeWebhook, invokeSchedule, invokeActivate } from './invoke.js';
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AASnD,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AASnD,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,6EAA6E;AAC7E,yEAAyE;AACzE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC","sourcesContent":["/**\n * @ekanos/sdk/testing — the partner test harness surface.\n *\n * `createMockContext()` is the day-1 in-memory `IntegrationContext`\n * (proposal §4): partners code and test against `ctx` here before anything\n * lands in a sandbox. Self-contained — no Supabase, no Vault, no network —\n * and enforcement (storage schemas, secret tiers, egress) is the same\n * shared implementation from `@ekanos/sdk/context` that production uses.\n *\n * Surface discipline: additions require an entry in\n * api-report.md, regenerated by `pnpm --filter @ekanos/sdk api-report`.\n */\n\nexport { createMockContext } from './mock-context';\nexport type {\n MockContextOptions,\n MockFetchHandler,\n MockIntegrationContext,\n RecordedFetchCall,\n RecordedLog,\n} from './mock-context';\n\n// Event-surface invocation: run declared webhook/schedule handlers locally,\n// with the same payload-validation and context-derivation semantics the real\n// transports will have. Used by partner unit tests and the harness Triggers\n// panel alike. `invokeActivate` does the same for the `onActivate` lifecycle\n// hook, used by partner unit tests and the harness's activation surface.\nexport { invokeWebhook, invokeSchedule, invokeActivate } from './invoke';\nexport type {\n DefinitionContextOptions,\n InvokeWebhookOptions,\n InvokeScheduleOptions,\n InvokeActivateOptions,\n WebhookInvocationOutcome,\n ScheduleInvocationOutcome,\n ActivateInvocationOutcome,\n} from './invoke';\n"]}
|
package/dist/testing/invoke.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* transport would, against a `createMockContext()` built FROM the definition
|
|
5
5
|
* (its slug, storage schemas, and egress list), so a handler unit test
|
|
6
6
|
* exercises the same schemas and the same egress allowlist production will.
|
|
7
|
+
* `invokeActivate()` does the same for the `onActivate` lifecycle hook.
|
|
7
8
|
*
|
|
8
9
|
* Transport semantics reproduced here, so they cannot drift from the docs:
|
|
9
10
|
* - the payload is parsed against `payloadSchema` BEFORE the handler runs;
|
|
@@ -12,7 +13,14 @@
|
|
|
12
13
|
* logs it as skipped (one warn line on `ctx.logs`), it never verifies and
|
|
13
14
|
* the handler never does either;
|
|
14
15
|
* - a schedule invocation carries `{scheduledFor, invokedAt, trigger}` with
|
|
15
|
-
* `trigger: 'manual'` by default (a human pressed the button)
|
|
16
|
+
* `trigger: 'manual'` by default (a human pressed the button);
|
|
17
|
+
* - `invokeActivate()` simply awaits `onActivate(ctx)` and returns the
|
|
18
|
+
* context it ran against — a throw PROPAGATES here. The non-fatal
|
|
19
|
+
* (log-and-continue) handling described on `OnActivateHandler` is HOST
|
|
20
|
+
* POLICY, applied by the transport that calls the hook in production
|
|
21
|
+
* (and by the harness's activation surface locally); this helper is a
|
|
22
|
+
* bare invoker; a test asserting the non-fatal behavior should catch its
|
|
23
|
+
* own rejection.
|
|
16
24
|
*/
|
|
17
25
|
import type { IntegrationDefinition, ScheduleInvocation, ScheduleResult, StorageSchemas, WebhookEvent, WebhookResult } from '@ekanos/integration-schema';
|
|
18
26
|
import { type MockContextOptions, type MockIntegrationContext } from './mock-context.js';
|
|
@@ -48,6 +56,11 @@ export interface InvokeScheduleOptions<Schemas extends StorageSchemas = StorageS
|
|
|
48
56
|
/** The tick this invocation stands for. Defaults to now. */
|
|
49
57
|
scheduledFor?: string;
|
|
50
58
|
}
|
|
59
|
+
export type InvokeActivateOptions<Schemas extends StorageSchemas = StorageSchemas> = BaseInvokeOptions<Schemas>;
|
|
60
|
+
export interface ActivateInvocationOutcome<Schemas extends StorageSchemas = StorageSchemas> {
|
|
61
|
+
/** The context the handler ran against — assert on its recordings. */
|
|
62
|
+
ctx: MockIntegrationContext<Schemas>;
|
|
63
|
+
}
|
|
51
64
|
export interface WebhookInvocationOutcome<Schemas extends StorageSchemas = StorageSchemas> {
|
|
52
65
|
result: WebhookResult;
|
|
53
66
|
/** The event the handler received (payload already schema-parsed). */
|
|
@@ -74,4 +87,15 @@ export declare function invokeWebhook<Schemas extends StorageSchemas = StorageSc
|
|
|
74
87
|
* context it ran against.
|
|
75
88
|
*/
|
|
76
89
|
export declare function invokeSchedule<Schemas extends StorageSchemas = StorageSchemas>(definition: IntegrationDefinition<Schemas>, scheduleId: string, options?: InvokeScheduleOptions<Schemas>): Promise<ScheduleInvocationOutcome<Schemas>>;
|
|
90
|
+
/**
|
|
91
|
+
* Runs the definition's declared `onActivate` hook, the way the host would
|
|
92
|
+
* after an activation persists or activationData updates. Throws if the
|
|
93
|
+
* definition declares no `onActivate` — there is nothing to invoke, and a
|
|
94
|
+
* silent no-op would let a test believe it exercised a hook that does not
|
|
95
|
+
* exist. A throwing handler PROPAGATES from this helper: the non-fatal
|
|
96
|
+
* (log-a-warning, keep the activation) handling is host policy applied by
|
|
97
|
+
* whatever calls this in production/the harness, not by this bare invoker
|
|
98
|
+
* (see the module doc comment).
|
|
99
|
+
*/
|
|
100
|
+
export declare function invokeActivate<Schemas extends StorageSchemas = StorageSchemas>(definition: IntegrationDefinition<Schemas>, options?: InvokeActivateOptions<Schemas>): Promise<ActivateInvocationOutcome<Schemas>>;
|
|
77
101
|
export {};
|
package/dist/testing/invoke.js
CHANGED
|
@@ -80,4 +80,23 @@ export async function invokeSchedule(definition, scheduleId, options = {}) {
|
|
|
80
80
|
const result = await schedule.handler(ctx, invocation);
|
|
81
81
|
return { result, invocation, ctx };
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Runs the definition's declared `onActivate` hook, the way the host would
|
|
85
|
+
* after an activation persists or activationData updates. Throws if the
|
|
86
|
+
* definition declares no `onActivate` — there is nothing to invoke, and a
|
|
87
|
+
* silent no-op would let a test believe it exercised a hook that does not
|
|
88
|
+
* exist. A throwing handler PROPAGATES from this helper: the non-fatal
|
|
89
|
+
* (log-a-warning, keep the activation) handling is host policy applied by
|
|
90
|
+
* whatever calls this in production/the harness, not by this bare invoker
|
|
91
|
+
* (see the module doc comment).
|
|
92
|
+
*/
|
|
93
|
+
export async function invokeActivate(definition, options = {}) {
|
|
94
|
+
if (!definition.onActivate) {
|
|
95
|
+
throw new Error(`Integration "${definition.slug}" declares no onActivate hook — add ` +
|
|
96
|
+
`one to defineIntegration() before invoking it.`);
|
|
97
|
+
}
|
|
98
|
+
const ctx = contextFor(definition, options);
|
|
99
|
+
await definition.onActivate(ctx);
|
|
100
|
+
return { ctx };
|
|
101
|
+
}
|
|
83
102
|
//# sourceMappingURL=invoke.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../src/testing/invoke.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Local execution of the declared event surfaces — `invokeWebhook()` and\n * `invokeSchedule()` deliver to a definition's handlers exactly the way a\n * transport would, against a `createMockContext()` built FROM the definition\n * (its slug, storage schemas, and egress list), so a handler unit test\n * exercises the same schemas and the same egress allowlist production will.\n *\n * Transport semantics reproduced here, so they cannot drift from the docs:\n * - the payload is parsed against `payloadSchema` BEFORE the handler runs;\n * an invalid payload throws and the handler never sees it;\n * - signature verification is the TRANSPORT's job — the local transport\n * logs it as skipped (one warn line on `ctx.logs`), it never verifies and\n * the handler never does either;\n * - a schedule invocation carries `{scheduledFor, invokedAt, trigger}` with\n * `trigger: 'manual'` by default (a human pressed the button).\n */\nimport type {\n IntegrationDefinition,\n ScheduleInvocation,\n ScheduleResult,\n StorageSchemas,\n WebhookEvent,\n WebhookResult,\n} from '@ekanos/integration-schema';\n\nimport {\n type MockContextOptions,\n type MockIntegrationContext,\n createMockContext,\n} from './mock-context';\n\n/**\n * Everything `createMockContext` takes except the fields the definition\n * itself is the authority on — the helpers derive `integration`,\n * `storageSchemas`, and `egress` from the definition so a test cannot\n * accidentally run a handler against schemas or an allowlist the definition\n * does not declare.\n */\nexport type DefinitionContextOptions<\n Schemas extends StorageSchemas = StorageSchemas,\n> = Omit<\n MockContextOptions<Schemas>,\n 'integration' | 'storageSchemas' | 'egress'\n>;\n\ninterface BaseInvokeOptions<Schemas extends StorageSchemas> {\n /**\n * Reuse an existing mock context so state (storage, secrets, logs)\n * accumulates across invocations — the harness does this. When set,\n * `context` wins and `contextOptions` must be omitted.\n */\n context?: MockIntegrationContext<Schemas>;\n /** Seeds and stubs for the context the helper creates. */\n contextOptions?: DefinitionContextOptions<Schemas>;\n}\n\nexport interface InvokeWebhookOptions<\n Schemas extends StorageSchemas = StorageSchemas,\n> extends BaseInvokeOptions<Schemas> {\n /** Delivery headers the event carries. Defaults to `{}`. */\n headers?: Record<string, string>;\n /** Transport-assigned event id. Defaults to a random UUID. */\n eventId?: string;\n /** ISO receipt time. Defaults to now. */\n receivedAt?: string;\n}\n\nexport interface InvokeScheduleOptions<\n Schemas extends StorageSchemas = StorageSchemas,\n> extends BaseInvokeOptions<Schemas> {\n /** Defaults to `'manual'` — a human pressed \"Run now\". */\n trigger?: ScheduleInvocation['trigger'];\n /** The tick this invocation stands for. Defaults to now. */\n scheduledFor?: string;\n}\n\nexport interface WebhookInvocationOutcome<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n result: WebhookResult;\n /** The event the handler received (payload already schema-parsed). */\n event: WebhookEvent;\n /** The context the handler ran against — assert on its recordings. */\n ctx: MockIntegrationContext<Schemas>;\n}\n\nexport interface ScheduleInvocationOutcome<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n result: ScheduleResult;\n invocation: ScheduleInvocation;\n ctx: MockIntegrationContext<Schemas>;\n}\n\nfunction contextFor<Schemas extends StorageSchemas>(\n definition: IntegrationDefinition<Schemas>,\n options: BaseInvokeOptions<Schemas>,\n): MockIntegrationContext<Schemas> {\n if (options.context) {\n if (options.contextOptions) {\n throw new TypeError(\n 'Pass either `context` (reuse an existing mock context) or ' +\n '`contextOptions` (seed a fresh one), not both — seeds cannot be ' +\n 'applied to a context that already exists.',\n );\n }\n return options.context;\n }\n\n return createMockContext<Schemas>({\n ...(options.contextOptions ?? {}),\n integration: { slug: definition.slug },\n ...(definition.storage ? { storageSchemas: definition.storage } : {}),\n egress: definition.egress ?? [],\n });\n}\n\nfunction listIds(ids: readonly string[]): string {\n return ids.length > 0 ? ids.map((id) => `\"${id}\"`).join(', ') : '(none)';\n}\n\n/**\n * Delivers one payload to one declared webhook, the way a transport would.\n * Throws if the id is undeclared or the payload fails `payloadSchema`;\n * returns the handler's result plus the event and the context it ran\n * against. Never verifies signatures — that is the transport's job, and the\n * local transport records the skip as a `warn` log line.\n */\nexport async function invokeWebhook<\n Schemas extends StorageSchemas = StorageSchemas,\n>(\n definition: IntegrationDefinition<Schemas>,\n webhookId: string,\n payload: unknown,\n options: InvokeWebhookOptions<Schemas> = {},\n): Promise<WebhookInvocationOutcome<Schemas>> {\n const webhook = (definition.webhooks ?? []).find((w) => w.id === webhookId);\n\n if (!webhook) {\n throw new Error(\n `Integration \"${definition.slug}\" declares no webhook \"${webhookId}\". ` +\n `Declared webhook ids: ${listIds((definition.webhooks ?? []).map((w) => w.id))}.`,\n );\n }\n\n const parsed = webhook.payloadSchema.safeParse(payload);\n\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';\n return ` - ${path}: ${issue.message}`;\n })\n .join('\\n');\n throw new Error(\n `Payload rejected by webhook \"${webhookId}\"'s payloadSchema — the ` +\n `transport refuses such a delivery before the handler runs:\\n${issues}`,\n );\n }\n\n const ctx = contextFor(definition, options);\n\n if (webhook.signature !== 'none') {\n ctx.logger.warn(\n {\n webhookId,\n header: webhook.signature.header,\n secretName: webhook.signature.secretName,\n },\n 'Signature verification SKIPPED (local transport). The host ingress ' +\n 'verifies this header against the named secret before the handler ' +\n 'runs — handlers never verify signatures themselves.',\n );\n }\n\n const event: WebhookEvent = {\n id: options.eventId ?? `evt_${crypto.randomUUID()}`,\n receivedAt: options.receivedAt ?? new Date().toISOString(),\n headers: options.headers ?? {},\n payload: parsed.data,\n };\n\n const result = await webhook.handler(ctx, event);\n\n return { result, event, ctx };\n}\n\n/**\n * Fires one declared schedule, the way the scheduler would. Throws if the id\n * is undeclared; returns the handler's result plus the invocation and the\n * context it ran against.\n */\nexport async function invokeSchedule<\n Schemas extends StorageSchemas = StorageSchemas,\n>(\n definition: IntegrationDefinition<Schemas>,\n scheduleId: string,\n options: InvokeScheduleOptions<Schemas> = {},\n): Promise<ScheduleInvocationOutcome<Schemas>> {\n const schedule = (definition.schedules ?? []).find(\n (s) => s.id === scheduleId,\n );\n\n if (!schedule) {\n throw new Error(\n `Integration \"${definition.slug}\" declares no schedule \"${scheduleId}\". ` +\n `Declared schedule ids: ${listIds((definition.schedules ?? []).map((s) => s.id))}.`,\n );\n }\n\n const ctx = contextFor(definition, options);\n const now = new Date().toISOString();\n\n const invocation: ScheduleInvocation = {\n scheduledFor: options.scheduledFor ?? now,\n invokedAt: now,\n trigger: options.trigger ?? 'manual',\n };\n\n const result = await schedule.handler(ctx, invocation);\n\n return { result, invocation, ctx };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../src/testing/invoke.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Local execution of the declared event surfaces — `invokeWebhook()` and\n * `invokeSchedule()` deliver to a definition's handlers exactly the way a\n * transport would, against a `createMockContext()` built FROM the definition\n * (its slug, storage schemas, and egress list), so a handler unit test\n * exercises the same schemas and the same egress allowlist production will.\n * `invokeActivate()` does the same for the `onActivate` lifecycle hook.\n *\n * Transport semantics reproduced here, so they cannot drift from the docs:\n * - the payload is parsed against `payloadSchema` BEFORE the handler runs;\n * an invalid payload throws and the handler never sees it;\n * - signature verification is the TRANSPORT's job — the local transport\n * logs it as skipped (one warn line on `ctx.logs`), it never verifies and\n * the handler never does either;\n * - a schedule invocation carries `{scheduledFor, invokedAt, trigger}` with\n * `trigger: 'manual'` by default (a human pressed the button);\n * - `invokeActivate()` simply awaits `onActivate(ctx)` and returns the\n * context it ran against — a throw PROPAGATES here. The non-fatal\n * (log-and-continue) handling described on `OnActivateHandler` is HOST\n * POLICY, applied by the transport that calls the hook in production\n * (and by the harness's activation surface locally); this helper is a\n * bare invoker; a test asserting the non-fatal behavior should catch its\n * own rejection.\n */\nimport type {\n IntegrationDefinition,\n ScheduleInvocation,\n ScheduleResult,\n StorageSchemas,\n WebhookEvent,\n WebhookResult,\n} from '@ekanos/integration-schema';\n\nimport {\n type MockContextOptions,\n type MockIntegrationContext,\n createMockContext,\n} from './mock-context';\n\n/**\n * Everything `createMockContext` takes except the fields the definition\n * itself is the authority on — the helpers derive `integration`,\n * `storageSchemas`, and `egress` from the definition so a test cannot\n * accidentally run a handler against schemas or an allowlist the definition\n * does not declare.\n */\nexport type DefinitionContextOptions<\n Schemas extends StorageSchemas = StorageSchemas,\n> = Omit<\n MockContextOptions<Schemas>,\n 'integration' | 'storageSchemas' | 'egress'\n>;\n\ninterface BaseInvokeOptions<Schemas extends StorageSchemas> {\n /**\n * Reuse an existing mock context so state (storage, secrets, logs)\n * accumulates across invocations — the harness does this. When set,\n * `context` wins and `contextOptions` must be omitted.\n */\n context?: MockIntegrationContext<Schemas>;\n /** Seeds and stubs for the context the helper creates. */\n contextOptions?: DefinitionContextOptions<Schemas>;\n}\n\nexport interface InvokeWebhookOptions<\n Schemas extends StorageSchemas = StorageSchemas,\n> extends BaseInvokeOptions<Schemas> {\n /** Delivery headers the event carries. Defaults to `{}`. */\n headers?: Record<string, string>;\n /** Transport-assigned event id. Defaults to a random UUID. */\n eventId?: string;\n /** ISO receipt time. Defaults to now. */\n receivedAt?: string;\n}\n\nexport interface InvokeScheduleOptions<\n Schemas extends StorageSchemas = StorageSchemas,\n> extends BaseInvokeOptions<Schemas> {\n /** Defaults to `'manual'` — a human pressed \"Run now\". */\n trigger?: ScheduleInvocation['trigger'];\n /** The tick this invocation stands for. Defaults to now. */\n scheduledFor?: string;\n}\n\nexport type InvokeActivateOptions<\n Schemas extends StorageSchemas = StorageSchemas,\n> = BaseInvokeOptions<Schemas>;\n\nexport interface ActivateInvocationOutcome<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n /** The context the handler ran against — assert on its recordings. */\n ctx: MockIntegrationContext<Schemas>;\n}\n\nexport interface WebhookInvocationOutcome<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n result: WebhookResult;\n /** The event the handler received (payload already schema-parsed). */\n event: WebhookEvent;\n /** The context the handler ran against — assert on its recordings. */\n ctx: MockIntegrationContext<Schemas>;\n}\n\nexport interface ScheduleInvocationOutcome<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n result: ScheduleResult;\n invocation: ScheduleInvocation;\n ctx: MockIntegrationContext<Schemas>;\n}\n\nfunction contextFor<Schemas extends StorageSchemas>(\n definition: IntegrationDefinition<Schemas>,\n options: BaseInvokeOptions<Schemas>,\n): MockIntegrationContext<Schemas> {\n if (options.context) {\n if (options.contextOptions) {\n throw new TypeError(\n 'Pass either `context` (reuse an existing mock context) or ' +\n '`contextOptions` (seed a fresh one), not both — seeds cannot be ' +\n 'applied to a context that already exists.',\n );\n }\n return options.context;\n }\n\n return createMockContext<Schemas>({\n ...(options.contextOptions ?? {}),\n integration: { slug: definition.slug },\n ...(definition.storage ? { storageSchemas: definition.storage } : {}),\n egress: definition.egress ?? [],\n });\n}\n\nfunction listIds(ids: readonly string[]): string {\n return ids.length > 0 ? ids.map((id) => `\"${id}\"`).join(', ') : '(none)';\n}\n\n/**\n * Delivers one payload to one declared webhook, the way a transport would.\n * Throws if the id is undeclared or the payload fails `payloadSchema`;\n * returns the handler's result plus the event and the context it ran\n * against. Never verifies signatures — that is the transport's job, and the\n * local transport records the skip as a `warn` log line.\n */\nexport async function invokeWebhook<\n Schemas extends StorageSchemas = StorageSchemas,\n>(\n definition: IntegrationDefinition<Schemas>,\n webhookId: string,\n payload: unknown,\n options: InvokeWebhookOptions<Schemas> = {},\n): Promise<WebhookInvocationOutcome<Schemas>> {\n const webhook = (definition.webhooks ?? []).find((w) => w.id === webhookId);\n\n if (!webhook) {\n throw new Error(\n `Integration \"${definition.slug}\" declares no webhook \"${webhookId}\". ` +\n `Declared webhook ids: ${listIds((definition.webhooks ?? []).map((w) => w.id))}.`,\n );\n }\n\n const parsed = webhook.payloadSchema.safeParse(payload);\n\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';\n return ` - ${path}: ${issue.message}`;\n })\n .join('\\n');\n throw new Error(\n `Payload rejected by webhook \"${webhookId}\"'s payloadSchema — the ` +\n `transport refuses such a delivery before the handler runs:\\n${issues}`,\n );\n }\n\n const ctx = contextFor(definition, options);\n\n if (webhook.signature !== 'none') {\n ctx.logger.warn(\n {\n webhookId,\n header: webhook.signature.header,\n secretName: webhook.signature.secretName,\n },\n 'Signature verification SKIPPED (local transport). The host ingress ' +\n 'verifies this header against the named secret before the handler ' +\n 'runs — handlers never verify signatures themselves.',\n );\n }\n\n const event: WebhookEvent = {\n id: options.eventId ?? `evt_${crypto.randomUUID()}`,\n receivedAt: options.receivedAt ?? new Date().toISOString(),\n headers: options.headers ?? {},\n payload: parsed.data,\n };\n\n const result = await webhook.handler(ctx, event);\n\n return { result, event, ctx };\n}\n\n/**\n * Fires one declared schedule, the way the scheduler would. Throws if the id\n * is undeclared; returns the handler's result plus the invocation and the\n * context it ran against.\n */\nexport async function invokeSchedule<\n Schemas extends StorageSchemas = StorageSchemas,\n>(\n definition: IntegrationDefinition<Schemas>,\n scheduleId: string,\n options: InvokeScheduleOptions<Schemas> = {},\n): Promise<ScheduleInvocationOutcome<Schemas>> {\n const schedule = (definition.schedules ?? []).find(\n (s) => s.id === scheduleId,\n );\n\n if (!schedule) {\n throw new Error(\n `Integration \"${definition.slug}\" declares no schedule \"${scheduleId}\". ` +\n `Declared schedule ids: ${listIds((definition.schedules ?? []).map((s) => s.id))}.`,\n );\n }\n\n const ctx = contextFor(definition, options);\n const now = new Date().toISOString();\n\n const invocation: ScheduleInvocation = {\n scheduledFor: options.scheduledFor ?? now,\n invokedAt: now,\n trigger: options.trigger ?? 'manual',\n };\n\n const result = await schedule.handler(ctx, invocation);\n\n return { result, invocation, ctx };\n}\n\n/**\n * Runs the definition's declared `onActivate` hook, the way the host would\n * after an activation persists or activationData updates. Throws if the\n * definition declares no `onActivate` — there is nothing to invoke, and a\n * silent no-op would let a test believe it exercised a hook that does not\n * exist. A throwing handler PROPAGATES from this helper: the non-fatal\n * (log-a-warning, keep the activation) handling is host policy applied by\n * whatever calls this in production/the harness, not by this bare invoker\n * (see the module doc comment).\n */\nexport async function invokeActivate<\n Schemas extends StorageSchemas = StorageSchemas,\n>(\n definition: IntegrationDefinition<Schemas>,\n options: InvokeActivateOptions<Schemas> = {},\n): Promise<ActivateInvocationOutcome<Schemas>> {\n if (!definition.onActivate) {\n throw new Error(\n `Integration \"${definition.slug}\" declares no onActivate hook — add ` +\n `one to defineIntegration() before invoking it.`,\n );\n }\n\n const ctx = contextFor(definition, options);\n\n await definition.onActivate(ctx);\n\n return { ctx };\n}\n"]}
|