@vornrun/connector-sdk 0.7.0-beta.17 → 0.7.0-beta.19
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 +19 -0
- package/dist/{check-Cv6UNBA4.d.ts → check-62s2GvcO.d.ts} +40 -2
- package/dist/{chunk-FHGC7LE7.js → chunk-ZKHXHE3O.js} +228 -53
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +35 -3
- package/dist/index.js +21 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -202,6 +202,25 @@ Two rules make a pull trigger reliable, and the SDK enforces both:
|
|
|
202
202
|
it. Use `>=` when filtering on `since` and sort ascending; returning a few
|
|
203
203
|
items again is free, because the SDK drops anything already delivered.
|
|
204
204
|
|
|
205
|
+
## Act through a signed-in window
|
|
206
|
+
|
|
207
|
+
A service with no API to key can still be reached as the person using it. Declare the `browser` rung with the page to sign in on, the origins the connector may act on, and a check that answers 2xx only while someone is signed in:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
auth: {
|
|
211
|
+
rung: 'browser',
|
|
212
|
+
browser: {
|
|
213
|
+
signInUrl: 'https://example.com/login',
|
|
214
|
+
origins: ['https://example.com', 'https://*.example.com'],
|
|
215
|
+
check: { url: 'https://example.com/api/me', identity: ['name', 'handle'] }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Vorn opens a window on a browser profile that belongs to one connection, and the person signs in there. The connector's code then gets `ctx.session.fetch` beside `ctx.fetch`. A call through `ctx.session.fetch` runs inside that signed-in window as a same-origin request, so the service sees its own page asking and no cookie reaches the connector. Calls outside `origins` are refused. `ctx.fetch` stays a plain fetch for public reads, such as a feed, which work before anyone signs in. A `browser` connector's declared `request` actions go through the window.
|
|
221
|
+
|
|
222
|
+
`--mock` serves signed-in calls from the same routes as every other call. A `--live` run from a terminal has no window, so it skips them.
|
|
223
|
+
|
|
205
224
|
## Dedupe strategies
|
|
206
225
|
|
|
207
226
|
`dedupe` tells the SDK how to recognize new items, and it then owns the cursor
|
|
@@ -73,6 +73,8 @@ interface PollContext {
|
|
|
73
73
|
now(): string;
|
|
74
74
|
/** Fetch with the SDK's retry and backoff applied. A poll is always a read. */
|
|
75
75
|
fetch: typeof fetch;
|
|
76
|
+
/** Present only when the connector signs in through a Vorn window. */
|
|
77
|
+
session?: SessionContext;
|
|
76
78
|
}
|
|
77
79
|
interface PollOutcome {
|
|
78
80
|
items: ConnectorItem[];
|
|
@@ -114,6 +116,8 @@ interface FetchContext {
|
|
|
114
116
|
now(): string;
|
|
115
117
|
/** Fetch with the SDK's retry and backoff applied. A fetch is always a read. */
|
|
116
118
|
fetch: typeof fetch;
|
|
119
|
+
/** Present only when the connector signs in through a Vorn window. */
|
|
120
|
+
session?: SessionContext;
|
|
117
121
|
}
|
|
118
122
|
/**
|
|
119
123
|
* What an upstream state should become when an item is imported as a task.
|
|
@@ -227,6 +231,8 @@ interface ActionContext {
|
|
|
227
231
|
* same resilience a declared request does, and tests can replace it.
|
|
228
232
|
*/
|
|
229
233
|
fetch: typeof fetch;
|
|
234
|
+
/** Present only when the connector signs in through a Vorn window. */
|
|
235
|
+
session?: SessionContext;
|
|
230
236
|
}
|
|
231
237
|
/**
|
|
232
238
|
* One step of reshaping a response.
|
|
@@ -369,9 +375,27 @@ interface PreflightResult {
|
|
|
369
375
|
* `none` needs nothing — installing it is the whole setup. `cli` borrows a
|
|
370
376
|
* login that already works on the machine, which is the rung to prefer
|
|
371
377
|
* whenever a mature tool is signed in anyway. `key` asks for a credential.
|
|
378
|
+
* `browser` signs in through a Vorn window for a service with no API to key.
|
|
372
379
|
* `oauth` is declared but not yet carried by the host.
|
|
373
380
|
*/
|
|
374
|
-
type AuthRung = 'none' | 'cli' | 'key' | 'oauth';
|
|
381
|
+
type AuthRung = 'none' | 'cli' | 'key' | 'browser' | 'oauth';
|
|
382
|
+
/** How a `browser` connector signs in, and the only origins its calls may reach. */
|
|
383
|
+
interface BrowserSignIn {
|
|
384
|
+
/** The page the Vorn window opens for signing in. */
|
|
385
|
+
signInUrl: string;
|
|
386
|
+
/** `https://host` or `https://*.host`; the sign-in page and the check must sit inside them. */
|
|
387
|
+
origins: string[];
|
|
388
|
+
/** Answers 2xx only when signed in; `identity` names the fields of its JSON that say who. */
|
|
389
|
+
check: {
|
|
390
|
+
url: string;
|
|
391
|
+
identity: string[];
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
/** The signed-in window, offered to a `browser` connector's code. */
|
|
395
|
+
interface SessionContext {
|
|
396
|
+
/** Runs the request inside the connection's signed-in window; cookies never reach the connector. */
|
|
397
|
+
fetch: typeof fetch;
|
|
398
|
+
}
|
|
375
399
|
/**
|
|
376
400
|
* What a connector needs before it can talk to anything.
|
|
377
401
|
*
|
|
@@ -408,6 +432,8 @@ interface ConnectorAuth {
|
|
|
408
432
|
};
|
|
409
433
|
/** Config field keys holding the credential. Required for `key`. */
|
|
410
434
|
keys?: string[];
|
|
435
|
+
/** Required for `browser`. */
|
|
436
|
+
browser?: BrowserSignIn;
|
|
411
437
|
}
|
|
412
438
|
/** What an options set is given to work out its choices. */
|
|
413
439
|
interface OptionsContext {
|
|
@@ -415,6 +441,8 @@ interface OptionsContext {
|
|
|
415
441
|
now(): string;
|
|
416
442
|
/** Fetch with the SDK's retry and backoff applied. Listing choices is a read. */
|
|
417
443
|
fetch: typeof fetch;
|
|
444
|
+
/** Present only when the connector signs in through a Vorn window. */
|
|
445
|
+
session?: SessionContext;
|
|
418
446
|
}
|
|
419
447
|
/**
|
|
420
448
|
* Answers the question "what can this field be?" against a live connection.
|
|
@@ -725,6 +753,10 @@ interface RunPollOptions {
|
|
|
725
753
|
now?: () => string;
|
|
726
754
|
/** Replaced by the harness and by tests; defaults to the global fetch. */
|
|
727
755
|
fetchImpl?: typeof fetch;
|
|
756
|
+
/** Replaced by the harness and by tests; defaults to the signed-in window Vorn serves. */
|
|
757
|
+
sessionFetchImpl?: typeof fetch;
|
|
758
|
+
/** The key Vorn gave this tool call, carried on each request through the window. */
|
|
759
|
+
sessionCall?: string;
|
|
728
760
|
retry?: RetryPolicy;
|
|
729
761
|
/** Replaced in tests so backoff costs no real time. */
|
|
730
762
|
sleep?: (ms: number) => Promise<void>;
|
|
@@ -747,6 +779,10 @@ interface RunActionOptions {
|
|
|
747
779
|
now?: () => string;
|
|
748
780
|
/** Replaced by the harness and by tests; defaults to the global fetch. */
|
|
749
781
|
fetchImpl?: typeof fetch;
|
|
782
|
+
/** Replaced by the harness and by tests; defaults to the signed-in window Vorn serves. */
|
|
783
|
+
sessionFetchImpl?: typeof fetch;
|
|
784
|
+
/** The key Vorn gave this tool call, carried on each request through the window. */
|
|
785
|
+
sessionCall?: string;
|
|
750
786
|
retry?: RetryPolicy;
|
|
751
787
|
/** Replaced in tests so backoff costs no real time. */
|
|
752
788
|
sleep?: (ms: number) => Promise<void>;
|
|
@@ -902,6 +938,8 @@ interface HarnessOptions {
|
|
|
902
938
|
now?: () => string;
|
|
903
939
|
/** Answer the connector's calls from the test rather than the network. */
|
|
904
940
|
fetchImpl?: typeof fetch;
|
|
941
|
+
/** Answer its signed-in calls; defaults to `fetchImpl`, so one stub serves both. */
|
|
942
|
+
sessionFetchImpl?: typeof fetch;
|
|
905
943
|
/** Fake clock for backoff, so a retry test costs no real time. */
|
|
906
944
|
sleep?: (ms: number) => Promise<void>;
|
|
907
945
|
}
|
|
@@ -1096,4 +1134,4 @@ declare function runConformance(connector: Connector, options?: CheckOptions): P
|
|
|
1096
1134
|
/** Render findings for a terminal. Returns an empty string when all clear. */
|
|
1097
1135
|
declare function formatFindings(findings: CheckFinding[]): string;
|
|
1098
1136
|
|
|
1099
|
-
export {
|
|
1137
|
+
export { MANIFEST_TOOL as $, type ActionRequest as A, type BundleRequest as B, type CheckFinding as C, type ConnectorHarness as D, type ExtensionPermission as E, type ConnectorIcon as F, type ConnectorKind as G, type ConnectorManifest as H, type ConnectorVerification as I, type DedupeStrategy as J, type DefaultWorkflow as K, type ExtensionAgent as L, type ExtensionContext as M, type NormalizedItem as N, type ExtensionContributions as O, type PollContext as P, type ExtensionPlatform as Q, type ExtensionUsage as R, type ExtensionUsageWindow as S, type TriggerDefinition as T, type FetchContext as U, type FooterContribution as V, type FooterItem as W, type HarnessOptions as X, type LinkContext as Y, type LinkHandled as Z, type LinkHandlerContribution as _, type BundleOutput as a, MAX_PACK_BYTES as a0, MAX_POLL_PAGES as a1, type ManifestContributions as a2, type MockCall as a3, type MockHostAnswers as a4, type MockHostRun as a5, type MockRoute as a6, MockRouteMissError as a7, type MockRun as a8, OPTIONS_TOOL as a9, lifecycleScriptFindings as aA, mockExtensionHost as aB, pollToolName as aC, readNearestPackageJson as aD, resilientFetch as aE, retryAfterMs as aF, runAction as aG, runConformance as aH, runOptions as aI, runPoll as aJ, withMockHttp as aK, type OptionsContext as aa, type OptionsLoader as ab, PREFLIGHT_TOOL as ac, type PaginationStrategy as ad, type PaneContribution as ae, type PollPage as af, type PreflightResult as ag, type ResilientFetchOptions as ah, type RetryPolicy as ai, type RunActionOptions as aj, type RunPollOptions as ak, type SessionContext as al, type StatusSuggestion as am, backoffMs as an, bundleDependencyFindings as ao, bundledRequireFindings as ap, checkConnector as aq, connectionSetup as ar, connectorManifest as as, createConnectorHarness as at, drainPoll as au, esbuildBundle as av, escapedMockHttp as aw, footerToolName as ax, formatFindings as ay, handlerToolName as az, type ExtensionHostMethod as b, type ConnectorDefinition as c, type Connector as d, type ExtensionDefinition as e, type ConnectorConfig as f, type ExtensionHost as g, type PollOutcome as h, type ConnectorItem as i, type PostReceiveOp as j, type ActionContext as k, type ActionDefinition as l, type ActionInputField as m, type ActionInputOption as n, type ActionInputType as o, type ActionOutputField as p, type ActivationPredicate as q, type AuthRung as r, type BrowserSignIn as s, CHECK_OWNERS as t, type CheckCode as u, type CheckOptions as v, type ConformanceRun as w, type ConnectionSetup as x, type ConnectorAuth as y, type ConnectorConfigField as z };
|
|
@@ -1,9 +1,134 @@
|
|
|
1
|
+
// src/loopback.ts
|
|
2
|
+
var LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "[::1]"];
|
|
3
|
+
function loopbackEndpoint(env, names, fail = (message) => new Error(message)) {
|
|
4
|
+
const url = env[names.urlVar]?.trim();
|
|
5
|
+
const token = env[names.tokenVar]?.trim();
|
|
6
|
+
if (!url || !token) throw fail(names.missing);
|
|
7
|
+
let parsed;
|
|
8
|
+
try {
|
|
9
|
+
parsed = new URL(url);
|
|
10
|
+
} catch {
|
|
11
|
+
throw fail(`${names.urlVar} is ${JSON.stringify(url)}, which is not a URL`);
|
|
12
|
+
}
|
|
13
|
+
if (parsed.protocol !== "http:" || !LOOPBACK_HOSTS.includes(parsed.hostname)) {
|
|
14
|
+
throw fail(
|
|
15
|
+
`${names.urlVar} is ${JSON.stringify(url)}; ${names.served}, over http on ${LOOPBACK_HOSTS.join(", ")}`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
return { url: url.replace(/\/$/, ""), token };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/session.ts
|
|
22
|
+
var BROWSER_HOST_ENV = "VORN_BROWSER_HOST";
|
|
23
|
+
var BROWSER_TOKEN_ENV = "VORN_BROWSER_TOKEN";
|
|
24
|
+
var SESSION_CALL_META = "vorn/sessionCall";
|
|
25
|
+
var SESSION_CALL_HEADER = "x-vorn-session-call";
|
|
26
|
+
var SessionUnavailableError = class extends Error {
|
|
27
|
+
/** Asking again cannot bring the window back, so the SDK's retries let this through at once. */
|
|
28
|
+
retryable = false;
|
|
29
|
+
constructor(message) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = "SessionUnavailableError";
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var SessionRefusedError = class extends Error {
|
|
35
|
+
retryable = false;
|
|
36
|
+
constructor(message) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.name = "SessionRefusedError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var SESSION_TIMEOUT_MS = 45e3;
|
|
42
|
+
var NULL_BODY_STATUSES = /* @__PURE__ */ new Set([204, 205, 304]);
|
|
43
|
+
function readReply(text) {
|
|
44
|
+
let parsed;
|
|
45
|
+
try {
|
|
46
|
+
parsed = JSON.parse(text);
|
|
47
|
+
} catch {
|
|
48
|
+
throw new Error("The signed-in window answered with a body that is not JSON");
|
|
49
|
+
}
|
|
50
|
+
const reply2 = parsed;
|
|
51
|
+
if (!parsed || typeof parsed !== "object" || typeof reply2.status !== "number") {
|
|
52
|
+
throw new Error("The signed-in window answered without a status");
|
|
53
|
+
}
|
|
54
|
+
return reply2;
|
|
55
|
+
}
|
|
56
|
+
var refusal = (text) => text.trim() || void 0;
|
|
57
|
+
function createSessionFetch(options = {}) {
|
|
58
|
+
const env = options.env ?? process.env;
|
|
59
|
+
const call = options.fetchImpl ?? fetch;
|
|
60
|
+
return (async (input, init) => {
|
|
61
|
+
const { url, token } = loopbackEndpoint(
|
|
62
|
+
env,
|
|
63
|
+
{
|
|
64
|
+
urlVar: BROWSER_HOST_ENV,
|
|
65
|
+
tokenVar: BROWSER_TOKEN_ENV,
|
|
66
|
+
missing: `This connector acts through a signed-in Vorn window; run it from Vorn, which sets ${BROWSER_HOST_ENV}`,
|
|
67
|
+
served: "the endpoint is served on this machine"
|
|
68
|
+
},
|
|
69
|
+
(message) => new SessionUnavailableError(message)
|
|
70
|
+
);
|
|
71
|
+
const request = new Request(input, init);
|
|
72
|
+
const body = request.body ? await request.text() : void 0;
|
|
73
|
+
const answer = await call(`${url}/fetch`, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
headers: {
|
|
76
|
+
authorization: `Bearer ${token}`,
|
|
77
|
+
"content-type": "application/json",
|
|
78
|
+
...options.call && { [SESSION_CALL_HEADER]: options.call }
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify({
|
|
81
|
+
url: request.url,
|
|
82
|
+
method: request.method,
|
|
83
|
+
headers: Object.fromEntries(request.headers),
|
|
84
|
+
...body !== void 0 && { body }
|
|
85
|
+
}),
|
|
86
|
+
signal: AbortSignal.any([request.signal, AbortSignal.timeout(SESSION_TIMEOUT_MS)])
|
|
87
|
+
});
|
|
88
|
+
const text = await answer.text();
|
|
89
|
+
if (answer.status === 503) {
|
|
90
|
+
throw new SessionUnavailableError(
|
|
91
|
+
refusal(text) ?? "Vorn could not reach the signed-in window"
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
if (!answer.ok) {
|
|
95
|
+
throw new SessionRefusedError(
|
|
96
|
+
refusal(text) ?? `The signed-in window refused the call with HTTP ${answer.status}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
const reply2 = readReply(text);
|
|
100
|
+
return new Response(NULL_BODY_STATUSES.has(reply2.status) ? null : reply2.body ?? "", {
|
|
101
|
+
status: reply2.status,
|
|
102
|
+
...reply2.headers && { headers: reply2.headers }
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/origins.ts
|
|
108
|
+
var ORIGIN_PATTERN = /^https:\/\/(\*\.)?[a-z0-9-]+(\.[a-z0-9-]+)+$/i;
|
|
109
|
+
function withinOrigins(origins, url) {
|
|
110
|
+
let parsed;
|
|
111
|
+
try {
|
|
112
|
+
parsed = new URL(url);
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
if (parsed.protocol !== "https:" || parsed.port !== "") return false;
|
|
117
|
+
const target = parsed.hostname.toLowerCase();
|
|
118
|
+
return origins.some((origin) => {
|
|
119
|
+
if (!ORIGIN_PATTERN.test(origin)) return false;
|
|
120
|
+
const wildcard = origin.startsWith("https://*.");
|
|
121
|
+
const host = origin.slice(wildcard ? "https://*.".length : "https://".length).toLowerCase();
|
|
122
|
+
return wildcard ? target.endsWith(`.${host}`) : target === host;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
1
126
|
// src/define.ts
|
|
2
127
|
var KEY_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
|
|
3
128
|
var PATH_DATA_PATTERN = /^[MmZzLlHhVvCcSsQqTtAa0-9\s,.\-+eE]+$/;
|
|
4
129
|
var VIEW_BOX_PATTERN = /^-?[\d.]+\s+-?[\d.]+\s+-?[\d.]+\s+-?[\d.]+$/;
|
|
5
130
|
var DEDUPE_STRATEGIES = ["timestamp", "lastItem"];
|
|
6
|
-
var AUTH_RUNGS = ["none", "cli", "key", "oauth"];
|
|
131
|
+
var AUTH_RUNGS = ["none", "cli", "key", "browser", "oauth"];
|
|
7
132
|
var EXTENSION_PERMISSIONS = [
|
|
8
133
|
"git.read",
|
|
9
134
|
"terminal.read",
|
|
@@ -106,15 +231,46 @@ function assertAuth(definition) {
|
|
|
106
231
|
}
|
|
107
232
|
}
|
|
108
233
|
}
|
|
109
|
-
if (auth.rung === "
|
|
234
|
+
if (auth.rung === "browser") assertBrowserSignIn(id, auth.browser);
|
|
235
|
+
if (auth.rung === "none" || auth.rung === "browser") {
|
|
110
236
|
const secret = (definition.config ?? []).find((field) => field.secret === true);
|
|
111
237
|
if (secret) {
|
|
238
|
+
const claim = auth.rung === "none" ? "needs no sign-in" : "signs in through a Vorn window";
|
|
112
239
|
throw new Error(
|
|
113
|
-
`Connector ${id} claims it
|
|
240
|
+
`Connector ${id} claims it ${claim} but declares secret field "${secret.key}"`
|
|
114
241
|
);
|
|
115
242
|
}
|
|
116
243
|
}
|
|
117
244
|
}
|
|
245
|
+
function assertBrowserSignIn(id, browser) {
|
|
246
|
+
if (!browser) {
|
|
247
|
+
throw new Error(
|
|
248
|
+
`Connector ${id} signs in through a Vorn window but declares no browser sign-in`
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
const origins = Array.isArray(browser.origins) ? browser.origins : [];
|
|
252
|
+
const bad = origins.find((origin) => typeof origin !== "string" || !ORIGIN_PATTERN.test(origin));
|
|
253
|
+
if (origins.length === 0 || bad !== void 0) {
|
|
254
|
+
throw new Error(
|
|
255
|
+
`Connector ${id} must name its origins as https://host or https://*.host` + (bad !== void 0 ? `; ${JSON.stringify(bad)} is neither` : "")
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
const places = [
|
|
259
|
+
["sign-in page", browser.signInUrl],
|
|
260
|
+
["signed-in check", browser.check?.url]
|
|
261
|
+
];
|
|
262
|
+
for (const [what, url] of places) {
|
|
263
|
+
if (typeof url !== "string" || !withinOrigins(origins, url)) {
|
|
264
|
+
throw new Error(
|
|
265
|
+
`Connector ${id} puts its ${what} ${JSON.stringify(url ?? "")} outside its origins`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const identity = browser.check?.identity;
|
|
270
|
+
if (!Array.isArray(identity) || identity.some((path) => typeof path !== "string" || !path.trim())) {
|
|
271
|
+
throw new Error(`Connector ${id} must name its identity fields as non-empty strings`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
118
274
|
function assertIdentity(kind, definition) {
|
|
119
275
|
if (!KEY_PATTERN.test(definition.id ?? "")) {
|
|
120
276
|
throw new Error(`${kind} id "${definition.id}" must start with a letter and be url-safe`);
|
|
@@ -909,27 +1065,13 @@ var HostReplyError = class extends Error {
|
|
|
909
1065
|
}
|
|
910
1066
|
};
|
|
911
1067
|
var HOST_TIMEOUT_MS = 15e3;
|
|
912
|
-
var LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "[::1]"];
|
|
913
1068
|
function endpoint(env) {
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
}
|
|
921
|
-
let parsed;
|
|
922
|
-
try {
|
|
923
|
-
parsed = new URL(url);
|
|
924
|
-
} catch {
|
|
925
|
-
throw new Error(`${HOST_URL_ENV} is ${JSON.stringify(url)}, which is not a URL`);
|
|
926
|
-
}
|
|
927
|
-
if (parsed.protocol !== "http:" || !LOOPBACK_HOSTS.includes(parsed.hostname)) {
|
|
928
|
-
throw new Error(
|
|
929
|
-
`${HOST_URL_ENV} is ${JSON.stringify(url)}; the bridge is served on this machine, over http on ${LOOPBACK_HOSTS.join(", ")}`
|
|
930
|
-
);
|
|
931
|
-
}
|
|
932
|
-
return { url: url.replace(/\/$/, ""), token };
|
|
1069
|
+
return loopbackEndpoint(env, {
|
|
1070
|
+
urlVar: HOST_URL_ENV,
|
|
1071
|
+
tokenVar: HOST_TOKEN_ENV,
|
|
1072
|
+
missing: `This extension was started without a host bridge; ${HOST_URL_ENV} and ${HOST_TOKEN_ENV} are set by Vorn`,
|
|
1073
|
+
served: "the bridge is served on this machine"
|
|
1074
|
+
});
|
|
933
1075
|
}
|
|
934
1076
|
function createExtensionHost(options) {
|
|
935
1077
|
const env = options.env ?? process.env;
|
|
@@ -1125,7 +1267,8 @@ async function pollWithDedupe(trigger, context) {
|
|
|
1125
1267
|
...state2 && { lastItemId: state2.id },
|
|
1126
1268
|
...context.limit !== void 0 && { limit: context.limit },
|
|
1127
1269
|
now: context.now,
|
|
1128
|
-
fetch: context.fetch
|
|
1270
|
+
fetch: context.fetch,
|
|
1271
|
+
...context.session && { session: context.session }
|
|
1129
1272
|
});
|
|
1130
1273
|
return lastItemPoll(fetched2, state2, context, polledAt);
|
|
1131
1274
|
}
|
|
@@ -1136,7 +1279,8 @@ async function pollWithDedupe(trigger, context) {
|
|
|
1136
1279
|
...since !== void 0 && { since },
|
|
1137
1280
|
...context.limit !== void 0 && { limit: context.limit },
|
|
1138
1281
|
now: context.now,
|
|
1139
|
-
fetch: context.fetch
|
|
1282
|
+
fetch: context.fetch,
|
|
1283
|
+
...context.session && { session: context.session }
|
|
1140
1284
|
});
|
|
1141
1285
|
return timestampPoll(fetched, state, context, polledAt);
|
|
1142
1286
|
}
|
|
@@ -1440,6 +1584,9 @@ function backoffMs(attempt, policy = {}) {
|
|
|
1440
1584
|
const max = policy.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
|
|
1441
1585
|
return Math.min(max, base * 2 ** attempt);
|
|
1442
1586
|
}
|
|
1587
|
+
function isFinal(error) {
|
|
1588
|
+
return error?.retryable === false;
|
|
1589
|
+
}
|
|
1443
1590
|
function resilientFetch(options) {
|
|
1444
1591
|
const attempts = Math.min(MAX_ATTEMPTS, Math.max(1, options.retry?.attempts ?? DEFAULT_ATTEMPTS));
|
|
1445
1592
|
const sleep = options.sleep ?? wait;
|
|
@@ -1462,7 +1609,7 @@ function resilientFetch(options) {
|
|
|
1462
1609
|
const delay = asked === void 0 ? backoffMs(attempt, options.retry) : Math.min(asked, ceiling);
|
|
1463
1610
|
if (!await pause(delay)) return response;
|
|
1464
1611
|
} catch (error) {
|
|
1465
|
-
if (!options.retryable || last) throw error;
|
|
1612
|
+
if (!options.retryable || last || isFinal(error)) throw error;
|
|
1466
1613
|
if (!await pause(backoffMs(attempt, options.retry))) throw error;
|
|
1467
1614
|
}
|
|
1468
1615
|
}
|
|
@@ -1472,6 +1619,19 @@ function resilientFetch(options) {
|
|
|
1472
1619
|
}
|
|
1473
1620
|
|
|
1474
1621
|
// src/runtime.ts
|
|
1622
|
+
function wrap(fetchImpl, options, retryable) {
|
|
1623
|
+
return resilientFetch({
|
|
1624
|
+
fetchImpl,
|
|
1625
|
+
retryable,
|
|
1626
|
+
...options.retry !== void 0 && { retry: options.retry },
|
|
1627
|
+
...options.sleep !== void 0 && { sleep: options.sleep }
|
|
1628
|
+
});
|
|
1629
|
+
}
|
|
1630
|
+
function sessionFor(connector, options, retryable) {
|
|
1631
|
+
if (connector.auth?.rung !== "browser") return void 0;
|
|
1632
|
+
const fetchImpl = options.sessionFetchImpl ?? createSessionFetch(options.sessionCall ? { call: options.sessionCall } : {});
|
|
1633
|
+
return { fetch: wrap(fetchImpl, options, retryable) };
|
|
1634
|
+
}
|
|
1475
1635
|
var MAX_POLL_PAGES = 1e3;
|
|
1476
1636
|
async function runPoll(connector, triggerType, options = {}) {
|
|
1477
1637
|
const trigger = connector.triggers.find((entry) => entry.type === triggerType);
|
|
@@ -1480,6 +1640,7 @@ async function runPoll(connector, triggerType, options = {}) {
|
|
|
1480
1640
|
}
|
|
1481
1641
|
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
1482
1642
|
const polledAt = now();
|
|
1643
|
+
const session = sessionFor(connector, options, true);
|
|
1483
1644
|
const context = {
|
|
1484
1645
|
config: options.config ?? {},
|
|
1485
1646
|
...options.since !== void 0 && { since: options.since },
|
|
@@ -1487,12 +1648,8 @@ async function runPoll(connector, triggerType, options = {}) {
|
|
|
1487
1648
|
...options.limit !== void 0 && { limit: options.limit },
|
|
1488
1649
|
now,
|
|
1489
1650
|
// A poll only reads, so every failure it meets is worth trying again.
|
|
1490
|
-
fetch:
|
|
1491
|
-
|
|
1492
|
-
retryable: true,
|
|
1493
|
-
...options.retry !== void 0 && { retry: options.retry },
|
|
1494
|
-
...options.sleep !== void 0 && { sleep: options.sleep }
|
|
1495
|
-
})
|
|
1651
|
+
fetch: wrap(options.fetchImpl ?? globalThis.fetch, options, true),
|
|
1652
|
+
...session && { session }
|
|
1496
1653
|
};
|
|
1497
1654
|
const outcome = typeof trigger.poll === "function" ? await trigger.poll(context) : await pollWithDedupe(trigger, context);
|
|
1498
1655
|
if (!outcome || !Array.isArray(outcome.items)) {
|
|
@@ -1530,15 +1687,12 @@ async function runOptions(connector, name, options = {}) {
|
|
|
1530
1687
|
if (!loader) {
|
|
1531
1688
|
throw new Error(`Connector ${connector.id} serves no options set "${name}"`);
|
|
1532
1689
|
}
|
|
1690
|
+
const session = sessionFor(connector, options, true);
|
|
1533
1691
|
const loaded = await loader({
|
|
1534
1692
|
config: options.config ?? {},
|
|
1535
1693
|
now: options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()),
|
|
1536
|
-
fetch:
|
|
1537
|
-
|
|
1538
|
-
retryable: true,
|
|
1539
|
-
...options.retry !== void 0 && { retry: options.retry },
|
|
1540
|
-
...options.sleep !== void 0 && { sleep: options.sleep }
|
|
1541
|
-
})
|
|
1694
|
+
fetch: wrap(options.fetchImpl ?? globalThis.fetch, options, true),
|
|
1695
|
+
...session && { session }
|
|
1542
1696
|
});
|
|
1543
1697
|
if (!Array.isArray(loaded)) {
|
|
1544
1698
|
throw new Error(`Options set "${name}" did not return an array`);
|
|
@@ -1597,19 +1751,15 @@ async function runAction(connector, actionType, args, options = {}) {
|
|
|
1597
1751
|
const config = options.config ?? {};
|
|
1598
1752
|
const method = (action.request?.method ?? "GET").toUpperCase();
|
|
1599
1753
|
const retryable = action.idempotent === true || action.request !== void 0 && SAFE_METHODS.has(method);
|
|
1600
|
-
const fetchImpl =
|
|
1601
|
-
|
|
1602
|
-
retryable,
|
|
1603
|
-
...options.retry !== void 0 && { retry: options.retry },
|
|
1604
|
-
...options.sleep !== void 0 && { sleep: options.sleep }
|
|
1605
|
-
});
|
|
1754
|
+
const fetchImpl = wrap(options.fetchImpl ?? globalThis.fetch, options, retryable);
|
|
1755
|
+
const session = sessionFor(connector, options, retryable);
|
|
1606
1756
|
if (action.request !== void 0) {
|
|
1607
1757
|
try {
|
|
1608
1758
|
return await executeRequest(
|
|
1609
1759
|
action.request,
|
|
1610
1760
|
action.postReceive,
|
|
1611
1761
|
{ args: coerced, config },
|
|
1612
|
-
{ fetchImpl }
|
|
1762
|
+
{ fetchImpl: session?.fetch ?? fetchImpl }
|
|
1613
1763
|
);
|
|
1614
1764
|
} catch (error) {
|
|
1615
1765
|
throw new Error(
|
|
@@ -1624,7 +1774,8 @@ async function runAction(connector, actionType, args, options = {}) {
|
|
|
1624
1774
|
const output = await action.run(coerced, {
|
|
1625
1775
|
config,
|
|
1626
1776
|
now: options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()),
|
|
1627
|
-
fetch: fetchImpl
|
|
1777
|
+
fetch: fetchImpl,
|
|
1778
|
+
...session && { session }
|
|
1628
1779
|
});
|
|
1629
1780
|
return output ?? {};
|
|
1630
1781
|
}
|
|
@@ -1692,10 +1843,12 @@ async function withMockHttp(routes, body) {
|
|
|
1692
1843
|
}
|
|
1693
1844
|
}
|
|
1694
1845
|
function createConnectorHarness(connector, harnessOptions = {}) {
|
|
1846
|
+
const signedIn = harnessOptions.sessionFetchImpl ?? harnessOptions.fetchImpl;
|
|
1695
1847
|
const defaults = (options = {}) => ({
|
|
1696
1848
|
...harnessOptions.config && { config: harnessOptions.config },
|
|
1697
1849
|
...harnessOptions.now && { now: harnessOptions.now },
|
|
1698
1850
|
...harnessOptions.fetchImpl && { fetchImpl: harnessOptions.fetchImpl },
|
|
1851
|
+
...signedIn && { sessionFetchImpl: signedIn },
|
|
1699
1852
|
...harnessOptions.sleep && { sleep: harnessOptions.sleep },
|
|
1700
1853
|
...options
|
|
1701
1854
|
});
|
|
@@ -1706,6 +1859,7 @@ function createConnectorHarness(connector, harnessOptions = {}) {
|
|
|
1706
1859
|
...harnessOptions.config && { config: harnessOptions.config },
|
|
1707
1860
|
...harnessOptions.now && { now: harnessOptions.now },
|
|
1708
1861
|
...harnessOptions.fetchImpl && { fetchImpl: harnessOptions.fetchImpl },
|
|
1862
|
+
...signedIn && { sessionFetchImpl: signedIn },
|
|
1709
1863
|
...harnessOptions.sleep && { sleep: harnessOptions.sleep }
|
|
1710
1864
|
}),
|
|
1711
1865
|
manifest: () => connectorManifest(connector),
|
|
@@ -1927,7 +2081,8 @@ async function mockFindings(connector, options) {
|
|
|
1927
2081
|
try {
|
|
1928
2082
|
await runAction(connector, action.type, args, {
|
|
1929
2083
|
config,
|
|
1930
|
-
...options.now && { now: options.now }
|
|
2084
|
+
...options.now && { now: options.now },
|
|
2085
|
+
sessionFetchImpl: globalThis.fetch
|
|
1931
2086
|
});
|
|
1932
2087
|
return void 0;
|
|
1933
2088
|
} catch (error) {
|
|
@@ -2116,6 +2271,9 @@ function liveRunnable(action) {
|
|
|
2116
2271
|
function liveExamines(connector) {
|
|
2117
2272
|
return connector.preflight !== void 0 || connector.actions.some(liveRunnable);
|
|
2118
2273
|
}
|
|
2274
|
+
function needsWindow(error) {
|
|
2275
|
+
return error instanceof SessionUnavailableError || error instanceof Error && error.cause instanceof SessionUnavailableError;
|
|
2276
|
+
}
|
|
2119
2277
|
async function liveFindings(connector, options) {
|
|
2120
2278
|
if (!options.live) return [];
|
|
2121
2279
|
const found = [];
|
|
@@ -2146,6 +2304,7 @@ async function liveFindings(connector, options) {
|
|
|
2146
2304
|
...options.now && { now: options.now }
|
|
2147
2305
|
});
|
|
2148
2306
|
} catch (error) {
|
|
2307
|
+
if (needsWindow(error)) continue;
|
|
2149
2308
|
const reason = error instanceof Error ? error.message : String(error);
|
|
2150
2309
|
found.push(
|
|
2151
2310
|
finding2(
|
|
@@ -3028,6 +3187,10 @@ function scaffoldFiles(options) {
|
|
|
3028
3187
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3029
3188
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3030
3189
|
import { z } from "zod";
|
|
3190
|
+
function sessionCallOf(extra) {
|
|
3191
|
+
const key = extra._meta?.[SESSION_CALL_META];
|
|
3192
|
+
return typeof key === "string" ? { sessionCall: key } : {};
|
|
3193
|
+
}
|
|
3031
3194
|
function json(value) {
|
|
3032
3195
|
return {
|
|
3033
3196
|
// Vorn reads `structuredContent` to build step output and to find the
|
|
@@ -3129,12 +3292,13 @@ function createConnectorServer(connector, options = {}) {
|
|
|
3129
3292
|
options: z.array(z.looseObject({ value: z.string(), label: z.string().optional() })).describe("The choices, each a value to send and words to show")
|
|
3130
3293
|
})
|
|
3131
3294
|
},
|
|
3132
|
-
async (args) => {
|
|
3295
|
+
async (args, extra) => {
|
|
3133
3296
|
try {
|
|
3134
3297
|
return json({
|
|
3135
3298
|
options: await runOptions(connector, args.name, {
|
|
3136
3299
|
config: config(),
|
|
3137
|
-
...options.now && { now: options.now }
|
|
3300
|
+
...options.now && { now: options.now },
|
|
3301
|
+
...sessionCallOf(extra)
|
|
3138
3302
|
})
|
|
3139
3303
|
});
|
|
3140
3304
|
} catch (error) {
|
|
@@ -3159,7 +3323,7 @@ function createConnectorServer(connector, options = {}) {
|
|
|
3159
3323
|
hasMore: z.boolean().describe("Whether another page is immediately available")
|
|
3160
3324
|
})
|
|
3161
3325
|
},
|
|
3162
|
-
async (args) => {
|
|
3326
|
+
async (args, extra) => {
|
|
3163
3327
|
try {
|
|
3164
3328
|
const limit = args.limit === void 0 ? void 0 : Number(args.limit);
|
|
3165
3329
|
if (limit !== void 0 && !Number.isFinite(limit)) {
|
|
@@ -3171,7 +3335,8 @@ function createConnectorServer(connector, options = {}) {
|
|
|
3171
3335
|
...args.since !== void 0 && { since: args.since },
|
|
3172
3336
|
...args.cursor !== void 0 && { cursor: args.cursor },
|
|
3173
3337
|
...limit !== void 0 && { limit },
|
|
3174
|
-
...options.now && { now: options.now }
|
|
3338
|
+
...options.now && { now: options.now },
|
|
3339
|
+
...sessionCallOf(extra)
|
|
3175
3340
|
})
|
|
3176
3341
|
);
|
|
3177
3342
|
} catch (error) {
|
|
@@ -3253,12 +3418,13 @@ function createConnectorServer(connector, options = {}) {
|
|
|
3253
3418
|
inputSchema: inputShape(action.inputs ?? []),
|
|
3254
3419
|
outputSchema: outputSchema(action.outputs ?? [])
|
|
3255
3420
|
},
|
|
3256
|
-
async (args) => {
|
|
3421
|
+
async (args, extra) => {
|
|
3257
3422
|
try {
|
|
3258
3423
|
return json(
|
|
3259
3424
|
await runAction(connector, action.type, args, {
|
|
3260
3425
|
config: config(),
|
|
3261
|
-
...options.now && { now: options.now }
|
|
3426
|
+
...options.now && { now: options.now },
|
|
3427
|
+
...sessionCallOf(extra)
|
|
3262
3428
|
})
|
|
3263
3429
|
);
|
|
3264
3430
|
} catch (error) {
|
|
@@ -3275,6 +3441,15 @@ async function serveConnector(connector, options = {}) {
|
|
|
3275
3441
|
}
|
|
3276
3442
|
|
|
3277
3443
|
export {
|
|
3444
|
+
BROWSER_HOST_ENV,
|
|
3445
|
+
BROWSER_TOKEN_ENV,
|
|
3446
|
+
SESSION_CALL_META,
|
|
3447
|
+
SESSION_CALL_HEADER,
|
|
3448
|
+
SessionUnavailableError,
|
|
3449
|
+
SessionRefusedError,
|
|
3450
|
+
createSessionFetch,
|
|
3451
|
+
ORIGIN_PATTERN,
|
|
3452
|
+
withinOrigins,
|
|
3278
3453
|
EXTENSION_PERMISSIONS,
|
|
3279
3454
|
HOST_PERMISSIONS,
|
|
3280
3455
|
envNameFor,
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { B as BundleRequest, a as BundleOutput, C as CheckFinding } from './check-
|
|
2
|
+
import { B as BundleRequest, a as BundleOutput, C as CheckFinding } from './check-62s2GvcO.js';
|
|
3
3
|
|
|
4
4
|
interface CliDeps {
|
|
5
5
|
load(modulePath: string): Promise<unknown>;
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as ExtensionPermission, b as ExtensionHostMethod, c as ConnectorDefinition, d as Connector, e as ExtensionDefinition, f as ConnectorConfig, g as ExtensionHost, T as TriggerDefinition, P as PollContext, h as PollOutcome, i as ConnectorItem, N as NormalizedItem, j as PostReceiveOp, A as ActionRequest, B as BundleRequest, a as BundleOutput, C as CheckFinding } from './check-
|
|
2
|
-
export { k as ActionContext, l as ActionDefinition, m as ActionInputField, n as ActionInputOption, o as ActionInputType, p as ActionOutputField, q as ActivationPredicate, r as AuthRung, s as
|
|
1
|
+
import { E as ExtensionPermission, b as ExtensionHostMethod, c as ConnectorDefinition, d as Connector, e as ExtensionDefinition, f as ConnectorConfig, g as ExtensionHost, T as TriggerDefinition, P as PollContext, h as PollOutcome, i as ConnectorItem, N as NormalizedItem, j as PostReceiveOp, A as ActionRequest, B as BundleRequest, a as BundleOutput, C as CheckFinding } from './check-62s2GvcO.js';
|
|
2
|
+
export { k as ActionContext, l as ActionDefinition, m as ActionInputField, n as ActionInputOption, o as ActionInputType, p as ActionOutputField, q as ActivationPredicate, r as AuthRung, s as BrowserSignIn, t as CHECK_OWNERS, u as CheckCode, v as CheckOptions, w as ConformanceRun, x as ConnectionSetup, y as ConnectorAuth, z as ConnectorConfigField, D as ConnectorHarness, F as ConnectorIcon, G as ConnectorKind, H as ConnectorManifest, I as ConnectorVerification, J as DedupeStrategy, K as DefaultWorkflow, L as ExtensionAgent, M as ExtensionContext, O as ExtensionContributions, Q as ExtensionPlatform, R as ExtensionUsage, S as ExtensionUsageWindow, U as FetchContext, V as FooterContribution, W as FooterItem, X as HarnessOptions, Y as LinkContext, Z as LinkHandled, _ as LinkHandlerContribution, $ as MANIFEST_TOOL, a0 as MAX_PACK_BYTES, a1 as MAX_POLL_PAGES, a2 as ManifestContributions, a3 as MockCall, a4 as MockHostAnswers, a5 as MockHostRun, a6 as MockRoute, a7 as MockRouteMissError, a8 as MockRun, a9 as OPTIONS_TOOL, aa as OptionsContext, ab as OptionsLoader, ac as PREFLIGHT_TOOL, ad as PaginationStrategy, ae as PaneContribution, af as PollPage, ag as PreflightResult, ah as ResilientFetchOptions, ai as RetryPolicy, aj as RunActionOptions, ak as RunPollOptions, al as SessionContext, am as StatusSuggestion, an as backoffMs, ao as bundleDependencyFindings, ap as bundledRequireFindings, aq as checkConnector, ar as connectionSetup, as as connectorManifest, at as createConnectorHarness, au as drainPoll, av as esbuildBundle, aw as escapedMockHttp, ax as footerToolName, ay as formatFindings, az as handlerToolName, aA as lifecycleScriptFindings, aB as mockExtensionHost, aC as pollToolName, aD as readNearestPackageJson, aE as resilientFetch, aF as retryAfterMs, aG as runAction, aH as runConformance, aI as runOptions, aJ as runPoll, aK as withMockHttp } from './check-62s2GvcO.js';
|
|
3
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
4
|
|
|
5
5
|
/** Everything an extension may ask the host for; anything else is not grantable. */
|
|
@@ -59,6 +59,38 @@ interface HostBridgeOptions {
|
|
|
59
59
|
/** The host as an extension process reaches it, over the bridge Vorn served it. */
|
|
60
60
|
declare function createExtensionHost(options: HostBridgeOptions): ExtensionHost;
|
|
61
61
|
|
|
62
|
+
/** Where Vorn serves a browser-sign-in connector the window it signed in through. */
|
|
63
|
+
declare const BROWSER_HOST_ENV = "VORN_BROWSER_HOST";
|
|
64
|
+
declare const BROWSER_TOKEN_ENV = "VORN_BROWSER_TOKEN";
|
|
65
|
+
/** The tool call a window request belongs to, so Vorn can tell a step's own requests from another's. */
|
|
66
|
+
declare const SESSION_CALL_META = "vorn/sessionCall";
|
|
67
|
+
declare const SESSION_CALL_HEADER = "x-vorn-session-call";
|
|
68
|
+
/** The signed-in window could not make the call: Vorn is closed, too old, or not the caller. */
|
|
69
|
+
declare class SessionUnavailableError extends Error {
|
|
70
|
+
/** Asking again cannot bring the window back, so the SDK's retries let this through at once. */
|
|
71
|
+
readonly retryable = false;
|
|
72
|
+
constructor(message: string);
|
|
73
|
+
}
|
|
74
|
+
/** Vorn refused the call itself, for instance because it is off the connector's origins. */
|
|
75
|
+
declare class SessionRefusedError extends Error {
|
|
76
|
+
readonly retryable = false;
|
|
77
|
+
constructor(message: string);
|
|
78
|
+
}
|
|
79
|
+
interface SessionFetchOptions {
|
|
80
|
+
env?: NodeJS.ProcessEnv;
|
|
81
|
+
/** Replaced in tests so nothing opens a socket. */
|
|
82
|
+
fetchImpl?: typeof fetch;
|
|
83
|
+
/** The key of the tool call these requests belong to, from its MCP metadata. */
|
|
84
|
+
call?: string;
|
|
85
|
+
}
|
|
86
|
+
/** A fetch whose requests run inside the connection's signed-in Vorn window, so no cookie reaches this process. */
|
|
87
|
+
declare function createSessionFetch(options?: SessionFetchOptions): typeof fetch;
|
|
88
|
+
|
|
89
|
+
/** An origin a connector may act on: `https://host`, or `https://*.host` for every subdomain. */
|
|
90
|
+
declare const ORIGIN_PATTERN: RegExp;
|
|
91
|
+
/** Whether `url` is on one of the declared origins. */
|
|
92
|
+
declare function withinOrigins(origins: readonly string[], url: string): boolean;
|
|
93
|
+
|
|
62
94
|
/**
|
|
63
95
|
* Run a declarative trigger: call the author's `fetch`, then apply the chosen
|
|
64
96
|
* dedupe strategy.
|
|
@@ -223,4 +255,4 @@ declare function titleCase(id: string): string;
|
|
|
223
255
|
/** Every file a new connector or extension starts with, ready to build, check and pack. */
|
|
224
256
|
declare function scaffoldFiles(options: ScaffoldOptions): ScaffoldFile[];
|
|
225
257
|
|
|
226
|
-
export { ActionRequest, BundleOutput, BundleRequest, CheckFinding, Connector, ConnectorConfig, ConnectorDefinition, ConnectorItem, type ConnectorServerOptions, EXTENSION_PERMISSIONS, ExtensionDefinition, ExtensionHost, ExtensionHostMethod, ExtensionPermission, HOST_PERMISSIONS, HOST_TOKEN_ENV, HOST_URL_ENV, type HostBridgeOptions, MAX_REQUEST_PAGES, NormalizedItem, type PackOptions, type PackResult, PermissionDeniedError, PollContext, PollOutcome, PostReceiveOp, type RequestScope, type ResolvedRequest, type ScaffoldFile, type ScaffoldOptions, type Substitution, TriggerDefinition, applyPostReceive, asOutput, createConnectorServer, createExtensionHost, defineConnector, defineExtension, envNameFor, executeRequest, nextLink, normalizeItem, normalizeItems, packConnector, packFileName, pollWithDedupe, resolveConfig, resolveRequest, resolveTemplates, scaffoldFiles, serveConnector, titleCase, valueAt };
|
|
258
|
+
export { ActionRequest, BROWSER_HOST_ENV, BROWSER_TOKEN_ENV, BundleOutput, BundleRequest, CheckFinding, Connector, ConnectorConfig, ConnectorDefinition, ConnectorItem, type ConnectorServerOptions, EXTENSION_PERMISSIONS, ExtensionDefinition, ExtensionHost, ExtensionHostMethod, ExtensionPermission, HOST_PERMISSIONS, HOST_TOKEN_ENV, HOST_URL_ENV, type HostBridgeOptions, MAX_REQUEST_PAGES, NormalizedItem, ORIGIN_PATTERN, type PackOptions, type PackResult, PermissionDeniedError, PollContext, PollOutcome, PostReceiveOp, type RequestScope, type ResolvedRequest, SESSION_CALL_HEADER, SESSION_CALL_META, type ScaffoldFile, type ScaffoldOptions, type SessionFetchOptions, SessionRefusedError, SessionUnavailableError, type Substitution, TriggerDefinition, applyPostReceive, asOutput, createConnectorServer, createExtensionHost, createSessionFetch, defineConnector, defineExtension, envNameFor, executeRequest, nextLink, normalizeItem, normalizeItems, packConnector, packFileName, pollWithDedupe, resolveConfig, resolveRequest, resolveTemplates, scaffoldFiles, serveConnector, titleCase, valueAt, withinOrigins };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BROWSER_HOST_ENV,
|
|
3
|
+
BROWSER_TOKEN_ENV,
|
|
2
4
|
CHECK_OWNERS,
|
|
3
5
|
EXTENSION_PERMISSIONS,
|
|
4
6
|
HOST_PERMISSIONS,
|
|
@@ -10,8 +12,13 @@ import {
|
|
|
10
12
|
MAX_REQUEST_PAGES,
|
|
11
13
|
MockRouteMissError,
|
|
12
14
|
OPTIONS_TOOL,
|
|
15
|
+
ORIGIN_PATTERN,
|
|
13
16
|
PREFLIGHT_TOOL,
|
|
14
17
|
PermissionDeniedError,
|
|
18
|
+
SESSION_CALL_HEADER,
|
|
19
|
+
SESSION_CALL_META,
|
|
20
|
+
SessionRefusedError,
|
|
21
|
+
SessionUnavailableError,
|
|
15
22
|
applyPostReceive,
|
|
16
23
|
asOutput,
|
|
17
24
|
backoffMs,
|
|
@@ -23,6 +30,7 @@ import {
|
|
|
23
30
|
createConnectorHarness,
|
|
24
31
|
createConnectorServer,
|
|
25
32
|
createExtensionHost,
|
|
33
|
+
createSessionFetch,
|
|
26
34
|
defineConnector,
|
|
27
35
|
defineExtension,
|
|
28
36
|
drainPoll,
|
|
@@ -56,9 +64,12 @@ import {
|
|
|
56
64
|
serveConnector,
|
|
57
65
|
titleCase,
|
|
58
66
|
valueAt,
|
|
59
|
-
withMockHttp
|
|
60
|
-
|
|
67
|
+
withMockHttp,
|
|
68
|
+
withinOrigins
|
|
69
|
+
} from "./chunk-ZKHXHE3O.js";
|
|
61
70
|
export {
|
|
71
|
+
BROWSER_HOST_ENV,
|
|
72
|
+
BROWSER_TOKEN_ENV,
|
|
62
73
|
CHECK_OWNERS,
|
|
63
74
|
EXTENSION_PERMISSIONS,
|
|
64
75
|
HOST_PERMISSIONS,
|
|
@@ -70,8 +81,13 @@ export {
|
|
|
70
81
|
MAX_REQUEST_PAGES,
|
|
71
82
|
MockRouteMissError,
|
|
72
83
|
OPTIONS_TOOL,
|
|
84
|
+
ORIGIN_PATTERN,
|
|
73
85
|
PREFLIGHT_TOOL,
|
|
74
86
|
PermissionDeniedError,
|
|
87
|
+
SESSION_CALL_HEADER,
|
|
88
|
+
SESSION_CALL_META,
|
|
89
|
+
SessionRefusedError,
|
|
90
|
+
SessionUnavailableError,
|
|
75
91
|
applyPostReceive,
|
|
76
92
|
asOutput,
|
|
77
93
|
backoffMs,
|
|
@@ -83,6 +99,7 @@ export {
|
|
|
83
99
|
createConnectorHarness,
|
|
84
100
|
createConnectorServer,
|
|
85
101
|
createExtensionHost,
|
|
102
|
+
createSessionFetch,
|
|
86
103
|
defineConnector,
|
|
87
104
|
defineExtension,
|
|
88
105
|
drainPoll,
|
|
@@ -116,5 +133,6 @@ export {
|
|
|
116
133
|
serveConnector,
|
|
117
134
|
titleCase,
|
|
118
135
|
valueAt,
|
|
119
|
-
withMockHttp
|
|
136
|
+
withMockHttp,
|
|
137
|
+
withinOrigins
|
|
120
138
|
};
|