@vornrun/connector-sdk 0.7.0-beta.1 → 0.7.0-beta.11
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 +150 -2
- package/dist/chunk-XOP6JKBX.js +2220 -0
- package/dist/cli.d.ts +12 -1
- package/dist/cli.js +101 -11
- package/dist/index.d.ts +103 -418
- package/dist/index.js +58 -34
- package/dist/packaging-DFTuP4fr.d.ts +882 -0
- package/package.json +3 -1
- package/dist/chunk-457KOZUU.js +0 -773
package/README.md
CHANGED
|
@@ -84,6 +84,73 @@ await serveConnector(connector)
|
|
|
84
84
|
|
|
85
85
|
Publish it like any other package (`"bin": { "acme-connector": "dist/bin.js" }`).
|
|
86
86
|
|
|
87
|
+
`vorn-connector new acme` writes all of the above — package, entry, definition,
|
|
88
|
+
a test that needs no network — already building, checking and packing.
|
|
89
|
+
|
|
90
|
+
## Declare an action instead of writing one
|
|
91
|
+
|
|
92
|
+
Most actions put arguments into a request and keep part of the answer. Say that
|
|
93
|
+
and the SDK does the rest: `{{args.x}}` and `{{config.y}}` are filled in, an
|
|
94
|
+
argument nobody supplied is left out, a failed status is raised with what the
|
|
95
|
+
body said, and `postReceive` reshapes what came back.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
{
|
|
99
|
+
type: 'createIssue',
|
|
100
|
+
label: 'Create issue',
|
|
101
|
+
idempotent: false,
|
|
102
|
+
inputs: [{ key: 'title', label: 'Title', required: true }],
|
|
103
|
+
request: {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
url: '{{config.baseUrl}}/issues',
|
|
106
|
+
headers: { authorization: 'Bearer {{config.apiToken}}' },
|
|
107
|
+
body: { title: '{{args.title}}' }
|
|
108
|
+
},
|
|
109
|
+
// pick · rename · flatten · filter · map, applied left to right.
|
|
110
|
+
postReceive: [{ op: 'pick', keys: ['id', 'html_url'] }]
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Add `paginate` to follow every page rather than the first — `{ kind: 'cursor',
|
|
115
|
+
cursorPath: 'next', param: 'cursor' }`, `{ kind: 'page', param: 'page' }` or
|
|
116
|
+
`{ kind: 'link' }` — and the pages arrive concatenated.
|
|
117
|
+
|
|
118
|
+
Retry, backoff and rate-limit handling are applied for you, to declared
|
|
119
|
+
requests and to `context.fetch` alike. A read is always retried; a write only
|
|
120
|
+
when the action declares `idempotent: true`, because repeating a create makes a
|
|
121
|
+
second one. Prefer `context.fetch` over the global one in a hand-written action.
|
|
122
|
+
|
|
123
|
+
## Offer a field the choices it has
|
|
124
|
+
|
|
125
|
+
A `select` with fixed choices carries them; one whose choices only exist against
|
|
126
|
+
a live connection names a set the connector serves.
|
|
127
|
+
|
|
128
|
+
Choices are **suggestions, not a closed set**. Vorn draws a picker while the
|
|
129
|
+
value is one of them and its template-aware input whenever it is not, because a
|
|
130
|
+
step is entitled to compute the value from an earlier one — so the served tool
|
|
131
|
+
schema keeps the argument a plain string and lists the choices in its
|
|
132
|
+
description. Your action still receives whatever was finally sent, and it is
|
|
133
|
+
the connector's job to refuse a value it cannot use.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
options: { channels: async ({ config, fetch }) => ['general', 'random'] },
|
|
137
|
+
actions: [{
|
|
138
|
+
type: 'post',
|
|
139
|
+
label: 'Post',
|
|
140
|
+
inputs: [{ key: 'channel', label: 'Channel', type: 'select', loadOptions: 'channels' }],
|
|
141
|
+
request: { method: 'POST', url: '{{config.baseUrl}}/post/{{args.channel}}' }
|
|
142
|
+
}]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`loadOptions` is served today but not yet consumed: the SDK registers a
|
|
146
|
+
`vorn_connector_options` tool and answers it, and the manifest carries the set's
|
|
147
|
+
name, but the app does not fetch the list yet — such a field is edited as text
|
|
148
|
+
until it does. Declaring it now is what makes it work then; a field whose
|
|
149
|
+
choices are already known should use `options` instead.
|
|
150
|
+
|
|
151
|
+
A `json` argument arrives parsed. `builderHint` on a field is a note for whoever
|
|
152
|
+
writes the next connector, not for whoever runs this one.
|
|
153
|
+
|
|
87
154
|
## Poll a database instead of an API
|
|
88
155
|
|
|
89
156
|
Nothing about a trigger is HTTP-specific — it just returns items. A SQL pull
|
|
@@ -198,6 +265,48 @@ trigger and they are replayed through the real dedupe pipeline, so a connector
|
|
|
198
265
|
can be checked before anyone has credentials for it; pass `--live` to poll the
|
|
199
266
|
real source instead.
|
|
200
267
|
|
|
268
|
+
`--mock` is the full gate, and the one to run in CI. It answers every HTTP
|
|
269
|
+
request from routes instead of the network, runs each action on its own
|
|
270
|
+
declared arguments, and asks the questions `pack` asks about the package —
|
|
271
|
+
install-time scripts, and anything that would still need a registry at launch:
|
|
272
|
+
|
|
273
|
+
```console
|
|
274
|
+
$ npx vorn-connector check ./dist/index.js --mock --receipt verified.json
|
|
275
|
+
Verified manifest, auth, secrets, actions, dedupe, no-lifecycle-scripts, keywords, no-runtime-deps, mock — wrote verified.json
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`--receipt <file>` writes what was verified, for a catalog to carry:
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{ "schema": 1, "version": "1.2.0", "checkedAt": "…", "checks": ["manifest", "…"] }
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
A check that could not run is left out rather than listed as passed, and a
|
|
285
|
+
connector with any error gets no receipt at all.
|
|
286
|
+
|
|
287
|
+
`--live` additionally asks `preflight` whether the connector can sign in, then
|
|
288
|
+
runs each action that declared `idempotent: true`. Actions that did not are
|
|
289
|
+
never called: a smoke test must leave nothing behind.
|
|
290
|
+
|
|
291
|
+
In a unit test the same stub is available directly, so an author can assert on
|
|
292
|
+
what their connector sent:
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
const { result, calls } = await harness.withMockHttp(
|
|
296
|
+
[{ url: '/api/messages', method: 'POST', body: { id: 'm-1' } }],
|
|
297
|
+
() => harness.execute('post', { text: 'hi' })
|
|
298
|
+
)
|
|
299
|
+
expect(calls[0].url).toBe('https://acme.test/api/messages')
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
A request no route matches is refused rather than served, so a test says which
|
|
303
|
+
call escaped instead of quietly reaching a real service.
|
|
304
|
+
|
|
305
|
+
The stub replaces `fetch`, and only `fetch`. A connector that shells out to a
|
|
306
|
+
CLI or opens its own socket is not intercepted by it, so `--mock` reports any
|
|
307
|
+
action the stub never heard from as `mock-not-observed` and leaves `mock` out
|
|
308
|
+
of the receipt rather than vouching for a run it did not see.
|
|
309
|
+
|
|
201
310
|
```ts
|
|
202
311
|
{
|
|
203
312
|
type: 'newTicket',
|
|
@@ -257,6 +366,38 @@ hand:
|
|
|
257
366
|
npx vorn-connector setup ./dist/index.js
|
|
258
367
|
```
|
|
259
368
|
|
|
369
|
+
### Where a config field is read from
|
|
370
|
+
|
|
371
|
+
A field is read from the environment variable it names in `env`, or from its
|
|
372
|
+
key in CONSTANT_CASE when it names none — `apiToken` becomes `API_TOKEN`. The
|
|
373
|
+
same rule decides what `--live` reads and what the host must set when it hands
|
|
374
|
+
a connector its credentials, so it is exported rather than kept private:
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
import { envNameFor } from '@vornrun/connector-sdk'
|
|
378
|
+
|
|
379
|
+
envNameFor('apiToken') // API_TOKEN
|
|
380
|
+
envNameFor('apiToken', 'GH_TOKEN') // GH_TOKEN — an explicit env always wins
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Anything computing these names on the host side should call this rather than
|
|
384
|
+
re-implement it, or the two will disagree about a field named `oauth2Token`.
|
|
385
|
+
|
|
386
|
+
## Pack it as a file
|
|
387
|
+
|
|
388
|
+
`vorn-connector pack` builds a single installable file: the manifest plus one
|
|
389
|
+
bundled entry with every dependency inlined.
|
|
390
|
+
|
|
391
|
+
```bash
|
|
392
|
+
npx vorn-connector pack ./dist/index.js --out ./release
|
|
393
|
+
# → release/acme-1.2.3.vorn.tgz
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Packing runs `check` first, then two gates a pack must pass: the source package
|
|
397
|
+
declares no install-time scripts, and nothing was left outside the bundle. A
|
|
398
|
+
pack installs by copying files, so it works with no registry reachable — drop
|
|
399
|
+
it on **Settings → Connectors** and Vorn launches it from disk.
|
|
400
|
+
|
|
260
401
|
### Ship an icon
|
|
261
402
|
|
|
262
403
|
Without one, a connector shows the generic MCP glyph and is hard to pick out
|
|
@@ -286,16 +427,23 @@ text color instead of fighting the theme.
|
|
|
286
427
|
## CLI
|
|
287
428
|
|
|
288
429
|
```
|
|
430
|
+
vorn-connector new <id> Scaffold a new connector, ready to build
|
|
289
431
|
vorn-connector manifest <module> Print the manifest as JSON
|
|
290
432
|
vorn-connector setup <module> [trigger] Print the Vorn connection settings
|
|
291
433
|
vorn-connector poll <module> <trigger> Run one poll against the environment
|
|
292
434
|
vorn-connector check <module> Verify the connector against the contract
|
|
435
|
+
vorn-connector pack <module> Build an installable .vorn.tgz pack
|
|
293
436
|
vorn-connector serve <module> Serve on stdio (what Vorn runs)
|
|
294
437
|
```
|
|
295
438
|
|
|
439
|
+
`new` accepts `--out <dir>`, `--name "Display Name"`, and `--repo-conventions`,
|
|
440
|
+
which shapes the package the way the connectors repository expects it (scoped
|
|
441
|
+
name, changelog, compiler and test settings); `pack` accepts `--out <dir>`.
|
|
442
|
+
|
|
296
443
|
`poll` accepts `--since <iso>` and `--limit <n>`, and reads the connector's
|
|
297
444
|
declared config from your shell environment — the fastest way to confirm
|
|
298
445
|
credentials and field mapping before wiring anything up.
|
|
299
446
|
|
|
300
|
-
`check` runs against declared `sample` data by default
|
|
301
|
-
|
|
447
|
+
`check` runs against declared `sample` data by default. `--mock` serves its
|
|
448
|
+
HTTP and runs every action, `--live` polls the real source and runs the actions
|
|
449
|
+
that are safe to repeat, and `--receipt <file>` writes down what was verified.
|