@tangle-network/hub-sdk 0.29.0-develop.20260819122040.176c418 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -6
- package/dist/index.d.ts +845 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +580 -203
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,284 @@
|
|
|
1
1
|
import { SSEChunkParser } from "@tangle-network/sdk-telemetry";
|
|
2
|
+
//#region src/json-init.ts
|
|
3
|
+
/** The init of a request whose body is JSON. Every client builds its bodies
|
|
4
|
+
* here, so the content type cannot drift from the encoding. */
|
|
5
|
+
function jsonInit(method, body) {
|
|
6
|
+
return {
|
|
7
|
+
method,
|
|
8
|
+
body: JSON.stringify(body),
|
|
9
|
+
headers: { "Content-Type": "application/json" }
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/allowances.ts
|
|
14
|
+
var HubAllowancesClient = class {
|
|
15
|
+
constructor(request) {
|
|
16
|
+
this.request = request;
|
|
17
|
+
}
|
|
18
|
+
async plan(meter) {
|
|
19
|
+
return (await this.request(this.path(meter), { method: "GET" })).plan;
|
|
20
|
+
}
|
|
21
|
+
async setPlan(meter, plan) {
|
|
22
|
+
return (await this.request(this.path(meter), this.body("PUT", plan))).plan;
|
|
23
|
+
}
|
|
24
|
+
/** Admit one turn or refuse it. Retrying the same `turnId` never counts twice. */
|
|
25
|
+
async admit(meter, input) {
|
|
26
|
+
return (await this.request(`${this.path(meter)}/turns`, this.body("POST", input))).allowance;
|
|
27
|
+
}
|
|
28
|
+
/** What the member's next turn would get, without counting anything. */
|
|
29
|
+
async status(meter, subject) {
|
|
30
|
+
const query = new URLSearchParams();
|
|
31
|
+
if (subject.role) query.set("role", subject.role);
|
|
32
|
+
if (subject.payer) query.set("payer", subject.payer);
|
|
33
|
+
if (subject.payerRole) query.set("payerRole", subject.payerRole);
|
|
34
|
+
const suffix = query.size ? `?${query}` : "";
|
|
35
|
+
return (await this.request(`${this.memberPath(meter, subject.member)}${suffix}`, { method: "GET" })).allowance;
|
|
36
|
+
}
|
|
37
|
+
/** Move a member to the paid allowance until `expiresAt` (the paid period's end). */
|
|
38
|
+
async grant(meter, member, input) {
|
|
39
|
+
return (await this.request(`${this.memberPath(meter, member)}/grant`, this.body("PUT", {
|
|
40
|
+
tier: "paid",
|
|
41
|
+
...input
|
|
42
|
+
}))).grant;
|
|
43
|
+
}
|
|
44
|
+
/** Synchronize a paid grant by durable product revision. Null expiry writes
|
|
45
|
+
* a retained revocation. A delayed older update is refused, never reactivated.
|
|
46
|
+
* There is no fallback to the unversioned grant endpoint on older servers. */
|
|
47
|
+
async syncGrant(meter, member, input) {
|
|
48
|
+
const { grant } = await this.request(`${this.memberPath(meter, member)}/grant/sync`, this.body("PUT", input));
|
|
49
|
+
if (grant.member !== member || grant.source !== input.source || grant.revision !== input.revision || grant.reference !== input.reference || grant.expiresAt !== (input.expiresAt === null ? null : new Date(input.expiresAt).toISOString())) throw new Error("The Hub returned a mismatched grant synchronization receipt");
|
|
50
|
+
return grant;
|
|
51
|
+
}
|
|
52
|
+
async revoke(meter, member) {
|
|
53
|
+
await this.request(`${this.memberPath(meter, member)}/grant`, { method: "DELETE" });
|
|
54
|
+
}
|
|
55
|
+
/** Turns per member and per line on one UTC day (default today). */
|
|
56
|
+
async usage(meter, day) {
|
|
57
|
+
const suffix = day ? `?day=${encodeURIComponent(day)}` : "";
|
|
58
|
+
return (await this.request(`${this.path(meter)}/usage${suffix}`, { method: "GET" })).usage;
|
|
59
|
+
}
|
|
60
|
+
path(meter) {
|
|
61
|
+
return `/v1/hub/allowances/${encodeURIComponent(meter)}`;
|
|
62
|
+
}
|
|
63
|
+
memberPath(meter, member) {
|
|
64
|
+
return `${this.path(meter)}/members/${encodeURIComponent(member)}`;
|
|
65
|
+
}
|
|
66
|
+
body(method, body) {
|
|
67
|
+
return jsonInit(method, body);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/apps.ts
|
|
72
|
+
function encodedId(id) {
|
|
73
|
+
if (typeof id !== "string" || !id || id.length > 256 || id === "." || id === "..") throw new Error("A bounded app or grant id is required");
|
|
74
|
+
return encodeURIComponent(id);
|
|
75
|
+
}
|
|
76
|
+
var HubAppsClient = class {
|
|
77
|
+
grants;
|
|
78
|
+
constructor(request) {
|
|
79
|
+
this.request = request;
|
|
80
|
+
this.grants = {
|
|
81
|
+
list: () => this.request("/v1/me/app-grants", { method: "GET" }),
|
|
82
|
+
revoke: async (grantId) => this.request(`/v1/me/app-grants/${encodedId(grantId)}/revoke`, { method: "POST" })
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
list() {
|
|
86
|
+
return this.request("/v1/apps", { method: "GET" });
|
|
87
|
+
}
|
|
88
|
+
/** The secret is returned only by creation; keep it in your server vault. */
|
|
89
|
+
create(input) {
|
|
90
|
+
return this.request("/v1/apps", jsonInit("POST", input));
|
|
91
|
+
}
|
|
92
|
+
/** Immutable association of two existing records with the same owner. */
|
|
93
|
+
async linkOAuthClient(appId, clientId) {
|
|
94
|
+
return this.request(`/v1/apps/${encodedId(appId)}/oidc-client`, jsonInit("POST", { clientId }));
|
|
95
|
+
}
|
|
96
|
+
async revoke(appId) {
|
|
97
|
+
return this.request(`/v1/apps/${encodedId(appId)}/revoke`, { method: "POST" });
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/inbound-webhooks.ts
|
|
102
|
+
var HubInboundWebhooksClient = class {
|
|
103
|
+
constructor(request) {
|
|
104
|
+
this.request = request;
|
|
105
|
+
}
|
|
106
|
+
async create(connectionId, options = {}) {
|
|
107
|
+
return this.request(this.path(connectionId), jsonInit("POST", options));
|
|
108
|
+
}
|
|
109
|
+
async get(connectionId) {
|
|
110
|
+
return this.request(this.path(connectionId), { method: "GET" });
|
|
111
|
+
}
|
|
112
|
+
/** Add one owned Linq WhatsApp number without rotating the webhook secret. */
|
|
113
|
+
async ensurePhoneNumber(connectionId, phoneNumberId) {
|
|
114
|
+
if (!phoneNumberId || phoneNumberId.length > 128 || !/^[\x21-\x7e]+$/.test(phoneNumberId)) throw new Error("A bounded phone-number id is required");
|
|
115
|
+
return this.request(`${this.path(connectionId)}/phone-numbers/ensure`, jsonInit("POST", { phoneNumberId }));
|
|
116
|
+
}
|
|
117
|
+
/** Remove event subscriptions first. This does not silently rotate a live URL. */
|
|
118
|
+
async delete(connectionId) {
|
|
119
|
+
return this.request(this.path(connectionId), { method: "DELETE" });
|
|
120
|
+
}
|
|
121
|
+
path(connectionId) {
|
|
122
|
+
if (!connectionId || connectionId.length > 256) throw new Error("A bounded connection id is required");
|
|
123
|
+
return `/v1/hub/connections/${encodeURIComponent(connectionId)}/inbound-webhook`;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/knowledge.ts
|
|
128
|
+
/** Runtime-only retrieval. The authenticated sandbox credential determines the
|
|
129
|
+
* scope on the server; neither a caller nor an agent can supply another scope. */
|
|
130
|
+
var HubKnowledgeClient = class {
|
|
131
|
+
constructor(request) {
|
|
132
|
+
this.request = request;
|
|
133
|
+
}
|
|
134
|
+
query(input, options) {
|
|
135
|
+
return this.request("/v1/knowledge/runtime/query", {
|
|
136
|
+
...jsonInit("POST", {
|
|
137
|
+
query: input.query,
|
|
138
|
+
...input.limit !== void 0 ? { limit: input.limit } : {}
|
|
139
|
+
}),
|
|
140
|
+
signal: options?.signal
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/lines.ts
|
|
146
|
+
/** The `on.schedule` mapping a Line schedule helper writes. */
|
|
147
|
+
function scheduleYaml(cron, timezone, until) {
|
|
148
|
+
return ` schedule: { ${[
|
|
149
|
+
`cron: ${JSON.stringify(cron)}`,
|
|
150
|
+
`timezone: ${JSON.stringify(timezone)}`,
|
|
151
|
+
...until ? [`until: ${JSON.stringify(until)}`] : []
|
|
152
|
+
].join(", ")} }`;
|
|
153
|
+
}
|
|
154
|
+
/** Line calls share HubClient authentication and envelope handling. */
|
|
155
|
+
var HubLinesClient = class {
|
|
156
|
+
members;
|
|
157
|
+
memberApplications;
|
|
158
|
+
checkins;
|
|
159
|
+
constructor(request, createWorkflow, requestApplicationDispatchCurrent) {
|
|
160
|
+
this.request = request;
|
|
161
|
+
this.createWorkflow = createWorkflow;
|
|
162
|
+
this.requestApplicationDispatchCurrent = requestApplicationDispatchCurrent;
|
|
163
|
+
this.members = { list: async (lineId) => (await this.request(`/v1/hub/lines/${encodeURIComponent(lineId)}/members`, { method: "GET" })).members };
|
|
164
|
+
const applicationPath = (lineId, memberId) => `/v1/hub/lines/${encodeURIComponent(lineId)}/members/${encodeURIComponent(memberId)}/application`;
|
|
165
|
+
this.memberApplications = {
|
|
166
|
+
get: async (lineId, memberId) => await this.request(applicationPath(lineId, memberId), { method: "GET" }),
|
|
167
|
+
select: async (lineId, memberId, input) => (await this.request(applicationPath(lineId, memberId), jsonInit("PUT", input))).selection,
|
|
168
|
+
clear: async (lineId, memberId, input) => {
|
|
169
|
+
await this.request(applicationPath(lineId, memberId), jsonInit("DELETE", input));
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
this.checkins = { schedule: (cron, options) => {
|
|
173
|
+
const name = options.name ?? `line-checkin-${crypto.randomUUID().slice(0, 8)}`;
|
|
174
|
+
const yaml = [
|
|
175
|
+
`name: ${JSON.stringify(name)}`,
|
|
176
|
+
"on:",
|
|
177
|
+
scheduleYaml(cron, options.timezone, options.until),
|
|
178
|
+
"do:",
|
|
179
|
+
" - agent.run:",
|
|
180
|
+
" line:",
|
|
181
|
+
` id: ${JSON.stringify(options.lineId)}`,
|
|
182
|
+
` member: ${JSON.stringify(options.member)}`,
|
|
183
|
+
` prompt: ${JSON.stringify(options.prompt)}`
|
|
184
|
+
].join("\n");
|
|
185
|
+
return this.createWorkflow(yaml);
|
|
186
|
+
} };
|
|
187
|
+
}
|
|
188
|
+
async scheduleSend(cron, options) {
|
|
189
|
+
const name = options.name ?? `line-send-${crypto.randomUUID().slice(0, 8)}`;
|
|
190
|
+
const yaml = [
|
|
191
|
+
`name: ${JSON.stringify(name)}`,
|
|
192
|
+
"on:",
|
|
193
|
+
scheduleYaml(cron, options.timezone, options.until),
|
|
194
|
+
"do:",
|
|
195
|
+
" - line.send:",
|
|
196
|
+
` lineId: ${JSON.stringify(options.lineId)}`,
|
|
197
|
+
` memberId: ${JSON.stringify(options.memberId)}`,
|
|
198
|
+
` text: ${JSON.stringify(options.text)}`,
|
|
199
|
+
...options.notBefore ? [` notBefore: ${JSON.stringify(options.notBefore)}`] : []
|
|
200
|
+
].join("\n");
|
|
201
|
+
return this.createWorkflow(yaml);
|
|
202
|
+
}
|
|
203
|
+
async context() {
|
|
204
|
+
return this.request("/v1/hub/lines/context", { method: "GET" });
|
|
205
|
+
}
|
|
206
|
+
async send(lineId, input) {
|
|
207
|
+
return this.request(`/v1/hub/lines/${encodeURIComponent(lineId)}/send`, jsonInit("POST", input));
|
|
208
|
+
}
|
|
209
|
+
/** Read an owner send's receipt, including its coded answer. Queued is not delivered. */
|
|
210
|
+
async sentMessage(lineId, messageId) {
|
|
211
|
+
return this.request(`/v1/hub/lines/${encodeURIComponent(lineId)}/outbox/${encodeURIComponent(messageId)}`, { method: "GET" });
|
|
212
|
+
}
|
|
213
|
+
async remind(lineId, input) {
|
|
214
|
+
return this.request(`/v1/hub/lines/${encodeURIComponent(lineId)}/remind`, jsonInit("POST", input));
|
|
215
|
+
}
|
|
216
|
+
async applicationDispatchCurrent(lineId, messageId, input, callbackBearer) {
|
|
217
|
+
if (!this.requestApplicationDispatchCurrent) throw new Error("Use HubClient to check application dispatch authority");
|
|
218
|
+
return (await this.requestApplicationDispatchCurrent(`/v1/hub/lines/${encodeURIComponent(lineId)}/messages/${encodeURIComponent(messageId)}/application-dispatch/current`, jsonInit("POST", input), callbackBearer)).current;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
//#endregion
|
|
222
|
+
//#region src/managed-numbers.ts
|
|
223
|
+
/** Administrative number operations through Hub's authenticated transport.
|
|
224
|
+
* A mutation is one attempt; an uncertain create reuses its quote and reference. */
|
|
225
|
+
var HubManagedNumbersClient = class {
|
|
226
|
+
constructor(request) {
|
|
227
|
+
this.request = request;
|
|
228
|
+
}
|
|
229
|
+
readiness() {
|
|
230
|
+
return this.request("/v1/hub/numbers/readiness", { method: "GET" });
|
|
231
|
+
}
|
|
232
|
+
/** One page of orders. Scope by `clientReference` to ask about one binding,
|
|
233
|
+
* and follow `nextCursor` for the rest; a page is never ownership evidence. */
|
|
234
|
+
list(query = {}) {
|
|
235
|
+
const params = new URLSearchParams();
|
|
236
|
+
if (query.clientReference !== void 0) params.set("clientReference", query.clientReference);
|
|
237
|
+
if (query.cursor !== void 0) params.set("cursor", query.cursor);
|
|
238
|
+
if (query.limit !== void 0) params.set("limit", String(query.limit));
|
|
239
|
+
const search = params.toString();
|
|
240
|
+
return this.request(`/v1/hub/numbers${search ? `?${search}` : ""}`, { method: "GET" });
|
|
241
|
+
}
|
|
242
|
+
get(id) {
|
|
243
|
+
return this.request(this.path(id), { method: "GET" });
|
|
244
|
+
}
|
|
245
|
+
quote(input) {
|
|
246
|
+
return this.request("/v1/hub/numbers/quote", this.post(input));
|
|
247
|
+
}
|
|
248
|
+
/** `clientReference` and `transport`, when given, must match the signed
|
|
249
|
+
* quote or Hub refuses the purchase with a conflict. */
|
|
250
|
+
create(input) {
|
|
251
|
+
return this.request("/v1/hub/numbers", this.post(input));
|
|
252
|
+
}
|
|
253
|
+
/** Fences references so no order can take them again. Call it as the last
|
|
254
|
+
* step before retiring the resource they name: a purchase that races the
|
|
255
|
+
* retirement is then refused (`409 number_reference_fenced`) instead of
|
|
256
|
+
* binding a line to a resource that is gone. Refused with
|
|
257
|
+
* `409 number_reference_held` while a live order holds one of them; cancel
|
|
258
|
+
* it first. A cancelled order no longer holds its reference, so the fence
|
|
259
|
+
* succeeds as soon as `cancel` returns, whether or not its release is still
|
|
260
|
+
* pending. Repeating a fence is harmless. */
|
|
261
|
+
fence(input) {
|
|
262
|
+
return this.request("/v1/hub/numbers/fences", this.post(input));
|
|
263
|
+
}
|
|
264
|
+
advance(id) {
|
|
265
|
+
return this.request(`${this.path(id)}/advance`, this.post({}));
|
|
266
|
+
}
|
|
267
|
+
cancel(id) {
|
|
268
|
+
return this.request(`${this.path(id)}/cancel`, this.post({}));
|
|
269
|
+
}
|
|
270
|
+
path(id) {
|
|
271
|
+
if (!/^num_[a-f0-9]{36}$/.test(id)) throw new Error("Invalid managed number order id");
|
|
272
|
+
return `/v1/hub/numbers/${encodeURIComponent(id)}`;
|
|
273
|
+
}
|
|
274
|
+
post(body) {
|
|
275
|
+
return jsonInit("POST", body);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
//#endregion
|
|
2
279
|
//#region src/redaction.ts
|
|
3
280
|
const SECRET_KEY_PATTERN = /(api[_-]?key|authorization|capability[_-]?token|token|secret)/i;
|
|
4
|
-
const SECRET_VALUE_PATTERN = /\b(?:sk-tan[-_]|hubcap_|hct_|gh[pousr]_)[A-Za-z0-9_
|
|
281
|
+
const SECRET_VALUE_PATTERN = /\b(?:sk-tan[-_]|hubcap_|hct_|lrc_|gh[pousr]_)[A-Za-z0-9_.=-]+\b/g;
|
|
5
282
|
function redactHubValue(value) {
|
|
6
283
|
if (typeof value === "string") return value.replace(SECRET_VALUE_PATTERN, "[REDACTED]");
|
|
7
284
|
if (Array.isArray(value)) return value.map((item) => redactHubValue(item));
|
|
@@ -26,16 +303,18 @@ function bodySnippet(body, max = 200) {
|
|
|
26
303
|
const trimmed = body.trim();
|
|
27
304
|
return trimmed.length > max ? `${trimmed.slice(0, max)}…` : trimmed;
|
|
28
305
|
}
|
|
29
|
-
function httpError(path, status, statusText, body, contentType) {
|
|
30
|
-
const suffix = statusText ? ` ${statusText}` : "";
|
|
306
|
+
function httpError(path, status, statusText, body, contentType, omitResponseDetails = false) {
|
|
307
|
+
const suffix = !omitResponseDetails && statusText ? ` ${statusText}` : "";
|
|
31
308
|
return new HubSdkError({
|
|
32
309
|
code: `HUB_HTTP_${status}`,
|
|
33
310
|
message: `Hub request ${path} failed: HTTP ${status}${suffix}`,
|
|
34
311
|
details: {
|
|
35
312
|
status,
|
|
36
313
|
path,
|
|
37
|
-
|
|
38
|
-
|
|
314
|
+
...omitResponseDetails ? {} : {
|
|
315
|
+
contentType: contentType || null,
|
|
316
|
+
bodySnippet: bodySnippet(body)
|
|
317
|
+
}
|
|
39
318
|
}
|
|
40
319
|
}, { status });
|
|
41
320
|
}
|
|
@@ -52,6 +331,9 @@ function isHubSuccessEnvelope(value) {
|
|
|
52
331
|
function isRecord$1(value) {
|
|
53
332
|
return typeof value === "object" && value !== null;
|
|
54
333
|
}
|
|
334
|
+
function isDispatchCurrentData(value) {
|
|
335
|
+
return isRecord$1(value) && typeof value.current === "boolean";
|
|
336
|
+
}
|
|
55
337
|
/** Read a wire field as a string, or "" when the server sent anything else.
|
|
56
338
|
* `raw` is that field straight off the parsed payload, before any check. */
|
|
57
339
|
function optString(raw) {
|
|
@@ -222,13 +504,69 @@ function nonEmpty(value) {
|
|
|
222
504
|
function readProcessEnv() {
|
|
223
505
|
return globalThis.process?.env ?? {};
|
|
224
506
|
}
|
|
225
|
-
var
|
|
507
|
+
var HubTransport = class {
|
|
226
508
|
baseUrl;
|
|
227
509
|
fetch;
|
|
228
510
|
apiKey;
|
|
229
511
|
authHeaders;
|
|
512
|
+
constructor(options) {
|
|
513
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
514
|
+
this.apiKey = options.apiKey;
|
|
515
|
+
this.authHeaders = options.authHeaders;
|
|
516
|
+
this.fetch = options.fetch ?? fetch.bind(globalThis);
|
|
517
|
+
}
|
|
518
|
+
async request(path, init, options = {}) {
|
|
519
|
+
const callerAuth = options.auth === "caller";
|
|
520
|
+
const response = await this.fetch(`${this.baseUrl}${path}`, {
|
|
521
|
+
...init,
|
|
522
|
+
headers: await this.buildHeaders(init.headers, callerAuth)
|
|
523
|
+
});
|
|
524
|
+
const status = response.status;
|
|
525
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
526
|
+
const bodyText = await response.text();
|
|
527
|
+
if (!contentType.includes("application/json")) throw httpError(path, status, response.statusText, bodyText, contentType, callerAuth);
|
|
528
|
+
let parsed;
|
|
529
|
+
try {
|
|
530
|
+
parsed = JSON.parse(bodyText);
|
|
531
|
+
} catch {
|
|
532
|
+
throw httpError(path, status, response.statusText, bodyText, contentType, callerAuth);
|
|
533
|
+
}
|
|
534
|
+
if (isHubErrorEnvelope(parsed)) {
|
|
535
|
+
if (callerAuth) throw new HubSdkError({
|
|
536
|
+
code: parsed.error.code,
|
|
537
|
+
message: `Hub request ${path} failed: HTTP ${status}`
|
|
538
|
+
}, { status });
|
|
539
|
+
throw new HubSdkError(parsed.error, { status });
|
|
540
|
+
}
|
|
541
|
+
if (isHubSuccessEnvelope(parsed)) {
|
|
542
|
+
if (callerAuth && !response.ok) throw httpError(path, status, response.statusText, bodyText, contentType, callerAuth);
|
|
543
|
+
if (options.validateData && !options.validateData(parsed.data)) throw new HubSdkError({
|
|
544
|
+
code: `HUB_HTTP_${status}`,
|
|
545
|
+
message: `Hub request ${path} returned invalid data`,
|
|
546
|
+
details: {
|
|
547
|
+
status,
|
|
548
|
+
path
|
|
549
|
+
}
|
|
550
|
+
}, { status });
|
|
551
|
+
return parsed.data;
|
|
552
|
+
}
|
|
553
|
+
throw httpError(path, status, response.statusText, bodyText, contentType, callerAuth);
|
|
554
|
+
}
|
|
555
|
+
async buildHeaders(headers, callerAuth = false) {
|
|
556
|
+
const mergedHeaders = new Headers({ Accept: "application/json" });
|
|
557
|
+
if (!callerAuth && this.apiKey) mergedHeaders.set("Authorization", `Bearer ${this.apiKey}`);
|
|
558
|
+
if (!callerAuth && this.authHeaders) for (const [key, value] of new Headers(await this.authHeaders())) mergedHeaders.set(key, value);
|
|
559
|
+
for (const [key, value] of new Headers(headers)) mergedHeaders.set(key, value);
|
|
560
|
+
return mergedHeaders;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
var HubClient = class HubClient extends HubTransport {
|
|
564
|
+
knowledge;
|
|
565
|
+
allowances;
|
|
566
|
+
apps;
|
|
230
567
|
connections;
|
|
231
568
|
channels;
|
|
569
|
+
numbers;
|
|
232
570
|
eventSubscriptions;
|
|
233
571
|
permissions;
|
|
234
572
|
tokens;
|
|
@@ -237,11 +575,13 @@ var HubClient = class HubClient {
|
|
|
237
575
|
audit;
|
|
238
576
|
githubApp;
|
|
239
577
|
workflows;
|
|
578
|
+
lines;
|
|
240
579
|
constructor(options) {
|
|
241
|
-
|
|
242
|
-
this.
|
|
243
|
-
this.
|
|
244
|
-
this.
|
|
580
|
+
super(options);
|
|
581
|
+
this.knowledge = new HubKnowledgeClient((path, init) => this.request(path, init));
|
|
582
|
+
this.allowances = new HubAllowancesClient((path, init) => this.request(path, init));
|
|
583
|
+
this.apps = new HubAppsClient((path, init) => this.request(path, init));
|
|
584
|
+
this.numbers = new HubManagedNumbersClient((path, init) => this.request(path, init));
|
|
245
585
|
this.connections = new HubConnectionsClient((path, init) => this.request(path, init));
|
|
246
586
|
this.channels = new HubChannelsClient((path, init) => this.request(path, init));
|
|
247
587
|
this.eventSubscriptions = new HubEventSubscriptionsClient((path, init) => this.request(path, init));
|
|
@@ -252,6 +592,23 @@ var HubClient = class HubClient {
|
|
|
252
592
|
this.audit = new HubAuditClient((path, init) => this.request(path, init));
|
|
253
593
|
this.githubApp = new HubGithubAppClient((path, init) => this.request(path, init));
|
|
254
594
|
this.workflows = new HubWorkflowsClient((path, init) => this.request(path, init), (path, init) => this.stream(path, init), (path, init) => this.requestBytes(path, init));
|
|
595
|
+
this.lines = new HubLinesClient((path, init) => this.request(path, init), (yaml) => this.workflows.create(yaml), (path, init, callbackBearer) => {
|
|
596
|
+
if (typeof callbackBearer !== "string" || !/^[\x21-\x7e]{16,512}$/.test(callbackBearer)) throw new HubSdkError({
|
|
597
|
+
code: "HUB_INVALID_INPUT",
|
|
598
|
+
message: "Application callback bearer is invalid"
|
|
599
|
+
});
|
|
600
|
+
const headers = new Headers(init.headers);
|
|
601
|
+
headers.set("Authorization", `Bearer ${callbackBearer}`);
|
|
602
|
+
return this.request(path, {
|
|
603
|
+
...init,
|
|
604
|
+
headers,
|
|
605
|
+
credentials: "omit",
|
|
606
|
+
redirect: "manual"
|
|
607
|
+
}, {
|
|
608
|
+
auth: "caller",
|
|
609
|
+
validateData: isDispatchCurrentData
|
|
610
|
+
});
|
|
611
|
+
});
|
|
255
612
|
}
|
|
256
613
|
static fromEnv(options = {}) {
|
|
257
614
|
const env = options.env ?? readProcessEnv();
|
|
@@ -265,25 +622,6 @@ var HubClient = class HubClient {
|
|
|
265
622
|
async status() {
|
|
266
623
|
return this.request("/v1/hub/status", { method: "GET" });
|
|
267
624
|
}
|
|
268
|
-
async request(path, init) {
|
|
269
|
-
const response = await this.fetch(`${this.baseUrl}${path}`, {
|
|
270
|
-
...init,
|
|
271
|
-
headers: await this.buildHeaders(init.headers)
|
|
272
|
-
});
|
|
273
|
-
const status = response.status;
|
|
274
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
275
|
-
const bodyText = await response.text();
|
|
276
|
-
if (!contentType.includes("application/json")) throw httpError(path, status, response.statusText, bodyText, contentType);
|
|
277
|
-
let parsed;
|
|
278
|
-
try {
|
|
279
|
-
parsed = JSON.parse(bodyText);
|
|
280
|
-
} catch {
|
|
281
|
-
throw httpError(path, status, response.statusText, bodyText, contentType);
|
|
282
|
-
}
|
|
283
|
-
if (isHubErrorEnvelope(parsed)) throw new HubSdkError(parsed.error, { status });
|
|
284
|
-
if (isHubSuccessEnvelope(parsed)) return parsed.data;
|
|
285
|
-
throw httpError(path, status, response.statusText, bodyText, contentType);
|
|
286
|
-
}
|
|
287
625
|
/**
|
|
288
626
|
* Open a streaming (Server-Sent Events) response and return its raw body.
|
|
289
627
|
* Shares auth-header building + `fetch` with {@link request}, but does NOT
|
|
@@ -350,25 +688,13 @@ var HubClient = class HubClient {
|
|
|
350
688
|
contentType
|
|
351
689
|
};
|
|
352
690
|
}
|
|
353
|
-
async buildHeaders(headers) {
|
|
354
|
-
const mergedHeaders = new Headers(headers);
|
|
355
|
-
if (!mergedHeaders.has("Accept")) mergedHeaders.set("Accept", "application/json");
|
|
356
|
-
if (this.apiKey) mergedHeaders.set("Authorization", `Bearer ${this.apiKey}`);
|
|
357
|
-
if (this.authHeaders) for (const [key, value] of new Headers(await this.authHeaders())) mergedHeaders.set(key, value);
|
|
358
|
-
for (const [key, value] of new Headers(headers)) mergedHeaders.set(key, value);
|
|
359
|
-
return mergedHeaders;
|
|
360
|
-
}
|
|
361
691
|
};
|
|
362
692
|
var HubTokensClient = class {
|
|
363
693
|
constructor(request) {
|
|
364
694
|
this.request = request;
|
|
365
695
|
}
|
|
366
696
|
async mint(options) {
|
|
367
|
-
return this.request("/v1/hub/tokens",
|
|
368
|
-
method: "POST",
|
|
369
|
-
body: JSON.stringify(options),
|
|
370
|
-
headers: { "Content-Type": "application/json" }
|
|
371
|
-
});
|
|
697
|
+
return this.request("/v1/hub/tokens", jsonInit("POST", options));
|
|
372
698
|
}
|
|
373
699
|
async list(options = {}) {
|
|
374
700
|
const searchParams = new URLSearchParams();
|
|
@@ -402,38 +728,22 @@ var HubPermissionsClient = class {
|
|
|
402
728
|
return this.request(`/v1/hub/policies?connectionId=${encodeURIComponent(connectionId)}`, { method: "GET" });
|
|
403
729
|
}
|
|
404
730
|
async set(input) {
|
|
405
|
-
return this.request("/v1/hub/policies",
|
|
406
|
-
method: "PUT",
|
|
407
|
-
body: JSON.stringify(input),
|
|
408
|
-
headers: { "Content-Type": "application/json" }
|
|
409
|
-
});
|
|
731
|
+
return this.request("/v1/hub/policies", jsonInit("PUT", input));
|
|
410
732
|
}
|
|
411
733
|
/** Reset an action to its default by deleting any stored override. */
|
|
412
734
|
async delete(input) {
|
|
413
|
-
return this.request("/v1/hub/policies",
|
|
414
|
-
method: "DELETE",
|
|
415
|
-
body: JSON.stringify(input),
|
|
416
|
-
headers: { "Content-Type": "application/json" }
|
|
417
|
-
});
|
|
735
|
+
return this.request("/v1/hub/policies", jsonInit("DELETE", input));
|
|
418
736
|
}
|
|
419
737
|
/** Bulk-allow every write action of a connection's provider. Reads are
|
|
420
738
|
* already allowed for sandbox agents; destructive actions stay `ask`.
|
|
421
739
|
* Idempotent: actions with an existing policy are left untouched. */
|
|
422
740
|
async allowWrites(connectionId) {
|
|
423
|
-
return this.request("/v1/hub/policies/allow-writes", {
|
|
424
|
-
method: "POST",
|
|
425
|
-
body: JSON.stringify({ connectionId }),
|
|
426
|
-
headers: { "Content-Type": "application/json" }
|
|
427
|
-
});
|
|
741
|
+
return this.request("/v1/hub/policies/allow-writes", jsonInit("POST", { connectionId }));
|
|
428
742
|
}
|
|
429
743
|
/** Inverse of `allowWrites`: delete only the rows it created for this
|
|
430
744
|
* connection. Manual per-action decisions are left intact. */
|
|
431
745
|
async revertWrites(connectionId) {
|
|
432
|
-
return this.request("/v1/hub/policies/revert-writes", {
|
|
433
|
-
method: "POST",
|
|
434
|
-
body: JSON.stringify({ connectionId }),
|
|
435
|
-
headers: { "Content-Type": "application/json" }
|
|
436
|
-
});
|
|
746
|
+
return this.request("/v1/hub/policies/revert-writes", jsonInit("POST", { connectionId }));
|
|
437
747
|
}
|
|
438
748
|
};
|
|
439
749
|
var HubToolsClient = class {
|
|
@@ -441,25 +751,17 @@ var HubToolsClient = class {
|
|
|
441
751
|
this.request = request;
|
|
442
752
|
}
|
|
443
753
|
async search(query, options = {}) {
|
|
444
|
-
return this.request("/v1/hub/tools/search", {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
limit: options.limit
|
|
450
|
-
}),
|
|
451
|
-
headers: { "Content-Type": "application/json" }
|
|
452
|
-
});
|
|
754
|
+
return this.request("/v1/hub/tools/search", jsonInit("POST", {
|
|
755
|
+
query,
|
|
756
|
+
provider: options.provider,
|
|
757
|
+
limit: options.limit
|
|
758
|
+
}));
|
|
453
759
|
}
|
|
454
760
|
async sources() {
|
|
455
761
|
return this.request("/v1/hub/tools/sources", { method: "GET" });
|
|
456
762
|
}
|
|
457
763
|
async describe(path) {
|
|
458
|
-
return this.request("/v1/hub/tools/describe", {
|
|
459
|
-
method: "POST",
|
|
460
|
-
body: JSON.stringify({ path }),
|
|
461
|
-
headers: { "Content-Type": "application/json" }
|
|
462
|
-
});
|
|
764
|
+
return this.request("/v1/hub/tools/describe", jsonInit("POST", { path }));
|
|
463
765
|
}
|
|
464
766
|
/**
|
|
465
767
|
* Run one hub tool. `raw` is the tool input: the SDK forwards it verbatim as
|
|
@@ -472,8 +774,9 @@ var HubToolsClient = class {
|
|
|
472
774
|
return await this.request("/v1/hub/exec", execInit);
|
|
473
775
|
} catch (error) {
|
|
474
776
|
if (!(error instanceof HubSdkError) || !requiresCapabilityToken(error)) throw error;
|
|
777
|
+
const approvalId = getApprovalId(error);
|
|
778
|
+
if (approvalId && options.approve !== true) throw error;
|
|
475
779
|
if (options.approve) {
|
|
476
|
-
const approvalId = getApprovalId(error);
|
|
477
780
|
if (!approvalId) throw error;
|
|
478
781
|
const approved = await this.request(`/v1/hub/approvals/${encodeURIComponent(approvalId)}/approve`, { method: "POST" });
|
|
479
782
|
validateApprovedExecution(approved, path, options.connectionId);
|
|
@@ -491,15 +794,11 @@ var HubToolsClient = class {
|
|
|
491
794
|
});
|
|
492
795
|
}
|
|
493
796
|
}
|
|
494
|
-
const minted = await this.request("/v1/hub/tokens", {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
provider: options.connectionId ? void 0 : path.split(".")[0]
|
|
500
|
-
}),
|
|
501
|
-
headers: { "Content-Type": "application/json" }
|
|
502
|
-
});
|
|
797
|
+
const minted = await this.request("/v1/hub/tokens", jsonInit("POST", {
|
|
798
|
+
actionPath: path,
|
|
799
|
+
connectionId: options.connectionId,
|
|
800
|
+
provider: options.connectionId ? void 0 : path.split(".")[0]
|
|
801
|
+
}));
|
|
503
802
|
return this.request("/v1/hub/exec", {
|
|
504
803
|
...execInit,
|
|
505
804
|
headers: {
|
|
@@ -509,16 +808,12 @@ var HubToolsClient = class {
|
|
|
509
808
|
});
|
|
510
809
|
}
|
|
511
810
|
buildExecInit(path, raw, options) {
|
|
512
|
-
return {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
idempotencyKey: options.idempotencyKey
|
|
519
|
-
}),
|
|
520
|
-
headers: { "Content-Type": "application/json" }
|
|
521
|
-
};
|
|
811
|
+
return jsonInit("POST", {
|
|
812
|
+
path,
|
|
813
|
+
input: raw,
|
|
814
|
+
connectionId: options.connectionId,
|
|
815
|
+
idempotencyKey: options.idempotencyKey
|
|
816
|
+
});
|
|
522
817
|
}
|
|
523
818
|
};
|
|
524
819
|
function requiresCapabilityToken(error) {
|
|
@@ -548,6 +843,17 @@ function validateApprovedExecution(approved, path, connectionId) {
|
|
|
548
843
|
}
|
|
549
844
|
});
|
|
550
845
|
}
|
|
846
|
+
const GITHUB_EXACT_CONNECT_SCOPES = [
|
|
847
|
+
"read:user",
|
|
848
|
+
"repo",
|
|
849
|
+
"read:org"
|
|
850
|
+
];
|
|
851
|
+
function sameOAuthScopeSet(left, right) {
|
|
852
|
+
if (!Array.isArray(left)) return false;
|
|
853
|
+
const leftSet = new Set(left);
|
|
854
|
+
const rightSet = new Set(right);
|
|
855
|
+
return leftSet.size === left.length && rightSet.size === right.length && leftSet.size === rightSet.size && [...leftSet].every((scope) => rightSet.has(scope));
|
|
856
|
+
}
|
|
551
857
|
var HubChannelsClient = class {
|
|
552
858
|
constructor(request) {
|
|
553
859
|
this.request = request;
|
|
@@ -556,11 +862,7 @@ var HubChannelsClient = class {
|
|
|
556
862
|
return this.request("/v1/hub/channels", { method: "GET" });
|
|
557
863
|
}
|
|
558
864
|
async createEmail(input = {}) {
|
|
559
|
-
return this.request("/v1/hub/channels/email",
|
|
560
|
-
method: "POST",
|
|
561
|
-
body: JSON.stringify(input),
|
|
562
|
-
headers: { "Content-Type": "application/json" }
|
|
563
|
-
});
|
|
865
|
+
return this.request("/v1/hub/channels/email", jsonInit("POST", input));
|
|
564
866
|
}
|
|
565
867
|
async delete(channelId) {
|
|
566
868
|
return this.request(`/v1/hub/channels/${encodeURIComponent(channelId)}`, { method: "DELETE" });
|
|
@@ -574,19 +876,17 @@ var HubEventSubscriptionsClient = class {
|
|
|
574
876
|
return this.request("/v1/hub/event-subscriptions", { method: "GET" });
|
|
575
877
|
}
|
|
576
878
|
async create(input) {
|
|
577
|
-
return this.request("/v1/hub/event-subscriptions",
|
|
578
|
-
method: "POST",
|
|
579
|
-
body: JSON.stringify(input),
|
|
580
|
-
headers: { "Content-Type": "application/json" }
|
|
581
|
-
});
|
|
879
|
+
return this.request("/v1/hub/event-subscriptions", jsonInit("POST", input));
|
|
582
880
|
}
|
|
583
881
|
async delete(subscriptionId) {
|
|
584
882
|
return this.request(`/v1/hub/event-subscriptions/${encodeURIComponent(subscriptionId)}`, { method: "DELETE" });
|
|
585
883
|
}
|
|
586
884
|
};
|
|
587
885
|
var HubConnectionsClient = class {
|
|
886
|
+
inboundWebhook;
|
|
588
887
|
constructor(request) {
|
|
589
888
|
this.request = request;
|
|
889
|
+
this.inboundWebhook = new HubInboundWebhooksClient(request);
|
|
590
890
|
}
|
|
591
891
|
async list() {
|
|
592
892
|
return this.request("/v1/hub/connections", { method: "GET" });
|
|
@@ -598,40 +898,38 @@ var HubConnectionsClient = class {
|
|
|
598
898
|
return this.request("/v1/hub/providers", { method: "GET" });
|
|
599
899
|
}
|
|
600
900
|
async start(provider, options = {}) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
901
|
+
if (options.requestedScopes !== void 0 && (provider !== "github" || !sameOAuthScopeSet(options.requestedScopes, GITHUB_EXACT_CONNECT_SCOPES))) throw new HubSdkError({
|
|
902
|
+
code: "HUB_INVALID_INPUT",
|
|
903
|
+
message: "GitHub requestedScopes must be read:user, repo, and read:org"
|
|
904
|
+
});
|
|
905
|
+
const started = await this.request(`/v1/hub/connections/${encodeURIComponent(provider)}/start`, jsonInit("POST", {
|
|
906
|
+
returnUrl: options.returnUrl,
|
|
907
|
+
cli: options.cli,
|
|
908
|
+
connectionParameters: options.connectionParameters,
|
|
909
|
+
requestedScopes: options.requestedScopes
|
|
910
|
+
}));
|
|
911
|
+
if (options.requestedScopes !== void 0 && (started.provider !== provider || !sameOAuthScopeSet(started.scopes, options.requestedScopes))) throw new HubSdkError({
|
|
912
|
+
code: "HUB_CONFIG_MISSING",
|
|
913
|
+
message: "Hub did not preserve the requested OAuth scopes"
|
|
609
914
|
});
|
|
915
|
+
return started;
|
|
610
916
|
}
|
|
611
917
|
async startWhatsappEmbeddedSignup(options = {}) {
|
|
612
|
-
return this.request("/v1/hub/connections/whatsapp-business/embedded-signup/start", {
|
|
613
|
-
method: "POST",
|
|
614
|
-
body: JSON.stringify({ returnUrl: options.returnUrl }),
|
|
615
|
-
headers: { "Content-Type": "application/json" }
|
|
616
|
-
});
|
|
918
|
+
return this.request("/v1/hub/connections/whatsapp-business/embedded-signup/start", jsonInit("POST", { returnUrl: options.returnUrl }));
|
|
617
919
|
}
|
|
618
920
|
async completeWhatsappEmbeddedSignup(input) {
|
|
619
|
-
return this.request("/v1/hub/connections/whatsapp-business/embedded-signup/complete",
|
|
620
|
-
method: "POST",
|
|
621
|
-
body: JSON.stringify(input),
|
|
622
|
-
headers: { "Content-Type": "application/json" }
|
|
623
|
-
});
|
|
921
|
+
return this.request("/v1/hub/connections/whatsapp-business/embedded-signup/complete", jsonInit("POST", input));
|
|
624
922
|
}
|
|
625
923
|
/** Connect a non-OAuth (api-key) connector by submitting the user's key.
|
|
626
924
|
* The server validates the key with a live probe before persisting and
|
|
627
925
|
* returns the created (or reconnected) connection — there is no redirect,
|
|
628
|
-
* unlike `start`.
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
});
|
|
926
|
+
* unlike `start`. Cloudbeds requires propertyId metadata and PriceLabs
|
|
927
|
+
* requires listing ID/PMS pairs; other providers have no metadata. */
|
|
928
|
+
async connectApiKey(provider, apiKey, metadata) {
|
|
929
|
+
return this.request(`/v1/hub/connections/${encodeURIComponent(provider)}/connect-key`, jsonInit("POST", {
|
|
930
|
+
apiKey,
|
|
931
|
+
...metadata === void 0 ? {} : { metadata }
|
|
932
|
+
}));
|
|
635
933
|
}
|
|
636
934
|
async revoke(connectionId) {
|
|
637
935
|
return this.request(`/v1/hub/connections/${encodeURIComponent(connectionId)}`, { method: "DELETE" });
|
|
@@ -659,11 +957,7 @@ var HubGithubAppClient = class {
|
|
|
659
957
|
this.request = request;
|
|
660
958
|
}
|
|
661
959
|
async mintInstallationToken(input) {
|
|
662
|
-
return this.request("/v1/hub/github-app/mint-installation-token",
|
|
663
|
-
method: "POST",
|
|
664
|
-
body: JSON.stringify(input),
|
|
665
|
-
headers: { "Content-Type": "application/json" }
|
|
666
|
-
});
|
|
960
|
+
return this.request("/v1/hub/github-app/mint-installation-token", jsonInit("POST", input));
|
|
667
961
|
}
|
|
668
962
|
/** Every installation the caller may act through — their own and any org's
|
|
669
963
|
* they were verified against. The management surface's read. */
|
|
@@ -738,11 +1032,7 @@ var HubWorkflowsClient = class {
|
|
|
738
1032
|
return this.request(`/v1/workflows/${encodeURIComponent(id)}`, { method: "GET" });
|
|
739
1033
|
}
|
|
740
1034
|
async create(yaml) {
|
|
741
|
-
return this.request("/v1/workflows", {
|
|
742
|
-
method: "POST",
|
|
743
|
-
body: JSON.stringify({ yaml }),
|
|
744
|
-
headers: { "Content-Type": "application/json" }
|
|
745
|
-
});
|
|
1035
|
+
return this.request("/v1/workflows", jsonInit("POST", { yaml }));
|
|
746
1036
|
}
|
|
747
1037
|
/**
|
|
748
1038
|
* Replace the workflow's definition from YAML (recompiled server-side,
|
|
@@ -753,14 +1043,10 @@ var HubWorkflowsClient = class {
|
|
|
753
1043
|
* concurrent modification, `NOT_FOUND` for an unknown/foreign id.
|
|
754
1044
|
*/
|
|
755
1045
|
async update(id, yaml, opts = {}) {
|
|
756
|
-
return this.request(`/v1/workflows/${encodeURIComponent(id)}`, {
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
...opts.note !== void 0 ? { note: opts.note } : {}
|
|
761
|
-
}),
|
|
762
|
-
headers: { "Content-Type": "application/json" }
|
|
763
|
-
});
|
|
1046
|
+
return this.request(`/v1/workflows/${encodeURIComponent(id)}`, jsonInit("PUT", {
|
|
1047
|
+
yaml,
|
|
1048
|
+
...opts.note !== void 0 ? { note: opts.note } : {}
|
|
1049
|
+
}));
|
|
764
1050
|
}
|
|
765
1051
|
async delete(id) {
|
|
766
1052
|
await this.request(`/v1/workflows/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
@@ -771,11 +1057,7 @@ var HubWorkflowsClient = class {
|
|
|
771
1057
|
* via `update`, but it can still be paused/resumed here).
|
|
772
1058
|
*/
|
|
773
1059
|
async setEnabled(id, enabled) {
|
|
774
|
-
return this.request(`/v1/workflows/${encodeURIComponent(id)}`, {
|
|
775
|
-
method: "PATCH",
|
|
776
|
-
body: JSON.stringify({ enabled }),
|
|
777
|
-
headers: { "Content-Type": "application/json" }
|
|
778
|
-
});
|
|
1060
|
+
return this.request(`/v1/workflows/${encodeURIComponent(id)}`, jsonInit("PATCH", { enabled }));
|
|
779
1061
|
}
|
|
780
1062
|
/**
|
|
781
1063
|
* One page of run history, newest first. Pass the previous page's
|
|
@@ -803,9 +1085,7 @@ var HubWorkflowsClient = class {
|
|
|
803
1085
|
async run(id, inputs, opts = {}) {
|
|
804
1086
|
const hasInputs = inputs !== void 0 && Object.keys(inputs).length > 0;
|
|
805
1087
|
return this.request(`/v1/workflows/${encodeURIComponent(id)}/run`, {
|
|
806
|
-
|
|
807
|
-
body: JSON.stringify(hasInputs ? { inputs } : {}),
|
|
808
|
-
headers: { "Content-Type": "application/json" },
|
|
1088
|
+
...jsonInit("POST", hasInputs ? { inputs } : {}),
|
|
809
1089
|
...opts.signal ? { signal: opts.signal } : {}
|
|
810
1090
|
});
|
|
811
1091
|
}
|
|
@@ -984,11 +1264,7 @@ var HubWorkflowsClient = class {
|
|
|
984
1264
|
* YAML no longer compiles, `CONFLICT` on a concurrent modification.
|
|
985
1265
|
*/
|
|
986
1266
|
async rollback(id, rev) {
|
|
987
|
-
return this.request(`/v1/workflows/${encodeURIComponent(id)}/rollback`, {
|
|
988
|
-
method: "POST",
|
|
989
|
-
body: JSON.stringify({ rev }),
|
|
990
|
-
headers: { "Content-Type": "application/json" }
|
|
991
|
-
});
|
|
1267
|
+
return this.request(`/v1/workflows/${encodeURIComponent(id)}/rollback`, jsonInit("POST", { rev }));
|
|
992
1268
|
}
|
|
993
1269
|
/**
|
|
994
1270
|
* Deterministic health stats over the workflow's last N terminal runs
|
|
@@ -1009,11 +1285,7 @@ var HubWorkflowsClient = class {
|
|
|
1009
1285
|
* until an owner approves.
|
|
1010
1286
|
*/
|
|
1011
1287
|
async propose(id, input) {
|
|
1012
|
-
return this.request(`/v1/workflows/${encodeURIComponent(id)}/proposals`,
|
|
1013
|
-
method: "POST",
|
|
1014
|
-
body: JSON.stringify(input),
|
|
1015
|
-
headers: { "Content-Type": "application/json" }
|
|
1016
|
-
});
|
|
1288
|
+
return this.request(`/v1/workflows/${encodeURIComponent(id)}/proposals`, jsonInit("POST", input));
|
|
1017
1289
|
}
|
|
1018
1290
|
/**
|
|
1019
1291
|
* Pending (proposed) and declined (rejected) revisions, newest first, with
|
|
@@ -1040,11 +1312,7 @@ var HubWorkflowsClient = class {
|
|
|
1040
1312
|
* pending proposal.
|
|
1041
1313
|
*/
|
|
1042
1314
|
async rejectProposal(id, rev, opts = {}) {
|
|
1043
|
-
return this.request(`/v1/workflows/${encodeURIComponent(id)}/proposals/${encodeURIComponent(String(rev))}/reject`, {
|
|
1044
|
-
method: "POST",
|
|
1045
|
-
body: JSON.stringify(opts.reason !== void 0 ? { reason: opts.reason } : {}),
|
|
1046
|
-
headers: { "Content-Type": "application/json" }
|
|
1047
|
-
});
|
|
1315
|
+
return this.request(`/v1/workflows/${encodeURIComponent(id)}/proposals/${encodeURIComponent(String(rev))}/reject`, jsonInit("POST", opts.reason !== void 0 ? { reason: opts.reason } : {}));
|
|
1048
1316
|
}
|
|
1049
1317
|
/**
|
|
1050
1318
|
* Mint a fresh webhook hook token, retiring the current one immediately.
|
|
@@ -1124,11 +1392,7 @@ var HubWorkflowsClient = class {
|
|
|
1124
1392
|
* value, stored and read back verbatim, so the client never gives it a shape.
|
|
1125
1393
|
*/
|
|
1126
1394
|
async putKv(id, key, raw) {
|
|
1127
|
-
return this.request(`/v1/workflows/${encodeURIComponent(id)}/kv/${encodeURIComponent(key)}`, {
|
|
1128
|
-
method: "PUT",
|
|
1129
|
-
body: JSON.stringify({ value: raw }),
|
|
1130
|
-
headers: { "Content-Type": "application/json" }
|
|
1131
|
-
});
|
|
1395
|
+
return this.request(`/v1/workflows/${encodeURIComponent(id)}/kv/${encodeURIComponent(key)}`, jsonInit("PUT", { value: raw }));
|
|
1132
1396
|
}
|
|
1133
1397
|
/**
|
|
1134
1398
|
* Compare-and-swap: the write lands only when the stored version still
|
|
@@ -1138,14 +1402,10 @@ var HubWorkflowsClient = class {
|
|
|
1138
1402
|
* a shape.
|
|
1139
1403
|
*/
|
|
1140
1404
|
async casKv(id, key, expectedVersion, raw) {
|
|
1141
|
-
return this.request(`/v1/workflows/${encodeURIComponent(id)}/kv/${encodeURIComponent(key)}/cas`, {
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
value: raw
|
|
1146
|
-
}),
|
|
1147
|
-
headers: { "Content-Type": "application/json" }
|
|
1148
|
-
});
|
|
1405
|
+
return this.request(`/v1/workflows/${encodeURIComponent(id)}/kv/${encodeURIComponent(key)}/cas`, jsonInit("POST", {
|
|
1406
|
+
expectedVersion,
|
|
1407
|
+
value: raw
|
|
1408
|
+
}));
|
|
1149
1409
|
}
|
|
1150
1410
|
/** Delete a key; idempotent — `deleted` reports whether a row was removed. */
|
|
1151
1411
|
async deleteKv(id, key) {
|
|
@@ -1165,11 +1425,7 @@ var HubWorkflowsClient = class {
|
|
|
1165
1425
|
* (400); an unknown template id throws `NOT_FOUND`.
|
|
1166
1426
|
*/
|
|
1167
1427
|
async instantiateTemplate(templateId, parameters) {
|
|
1168
|
-
return this.request(`/v1/workflows/templates/${encodeURIComponent(templateId)}/instantiate`, {
|
|
1169
|
-
method: "POST",
|
|
1170
|
-
body: JSON.stringify(parameters ? { parameters } : {}),
|
|
1171
|
-
headers: { "Content-Type": "application/json" }
|
|
1172
|
-
});
|
|
1428
|
+
return this.request(`/v1/workflows/templates/${encodeURIComponent(templateId)}/instantiate`, jsonInit("POST", parameters ? { parameters } : {}));
|
|
1173
1429
|
}
|
|
1174
1430
|
/**
|
|
1175
1431
|
* The caller's open decisions across all workflows — the always-available
|
|
@@ -1196,11 +1452,7 @@ var HubWorkflowsClient = class {
|
|
|
1196
1452
|
* (409 — answered, timed out, or cancelled first).
|
|
1197
1453
|
*/
|
|
1198
1454
|
async resolveRunDecision(id, runId, input) {
|
|
1199
|
-
return this.request(`/v1/workflows/${encodeURIComponent(id)}/runs/${encodeURIComponent(runId)}/decision/resolve`,
|
|
1200
|
-
method: "POST",
|
|
1201
|
-
body: JSON.stringify(input),
|
|
1202
|
-
headers: { "Content-Type": "application/json" }
|
|
1203
|
-
});
|
|
1455
|
+
return this.request(`/v1/workflows/${encodeURIComponent(id)}/runs/${encodeURIComponent(runId)}/decision/resolve`, jsonInit("POST", input));
|
|
1204
1456
|
}
|
|
1205
1457
|
/**
|
|
1206
1458
|
* Dry-run a YAML definition against the platform compiler without saving it.
|
|
@@ -1213,17 +1465,93 @@ var HubWorkflowsClient = class {
|
|
|
1213
1465
|
* the unconnected providers is the point.
|
|
1214
1466
|
*/
|
|
1215
1467
|
async validate(yaml, opts = {}) {
|
|
1216
|
-
return this.request("/v1/workflows/validate", {
|
|
1468
|
+
return this.request("/v1/workflows/validate", jsonInit("POST", {
|
|
1469
|
+
yaml,
|
|
1470
|
+
...opts.structural ? { structural: true } : {}
|
|
1471
|
+
}));
|
|
1472
|
+
}
|
|
1473
|
+
async schema() {
|
|
1474
|
+
return this.request("/v1/workflows/schema", { method: "GET" });
|
|
1475
|
+
}
|
|
1476
|
+
};
|
|
1477
|
+
//#endregion
|
|
1478
|
+
//#region src/broker.ts
|
|
1479
|
+
/** Server-only client. App secrets never become a user's general API key.
|
|
1480
|
+
* Every invocation mints and consumes one short-lived, exact-grant token. */
|
|
1481
|
+
var HubAppBrokerClient = class {
|
|
1482
|
+
baseUrl;
|
|
1483
|
+
fetcher;
|
|
1484
|
+
constructor(options) {
|
|
1485
|
+
this.options = options;
|
|
1486
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
1487
|
+
this.fetcher = options.fetch ?? fetch.bind(globalThis);
|
|
1488
|
+
}
|
|
1489
|
+
async token(path, body) {
|
|
1490
|
+
const response = await this.fetcher(`${this.baseUrl}${path}`, {
|
|
1217
1491
|
method: "POST",
|
|
1492
|
+
redirect: "error",
|
|
1493
|
+
headers: { "Content-Type": "application/json" },
|
|
1218
1494
|
body: JSON.stringify({
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1495
|
+
...body,
|
|
1496
|
+
client_id: this.options.clientId,
|
|
1497
|
+
client_secret: this.options.clientSecret
|
|
1498
|
+
})
|
|
1499
|
+
});
|
|
1500
|
+
const result = await response.json().catch(() => null);
|
|
1501
|
+
if (!response.ok || !result || typeof result !== "object" || Array.isArray(result)) throw new HubSdkError({
|
|
1502
|
+
code: "HUB_CONFIG_MISSING",
|
|
1503
|
+
message: "Application authorization is unavailable"
|
|
1504
|
+
}, { status: response.status });
|
|
1505
|
+
return result;
|
|
1506
|
+
}
|
|
1507
|
+
readToken(body) {
|
|
1508
|
+
if (typeof body.access_token !== "string" || !body.access_token.startsWith("sk-tan-broker-") || body.token_type !== "Bearer" || typeof body.expires_in !== "number" || !Number.isSafeInteger(body.expires_in) || body.expires_in <= 0 || typeof body.scope !== "string") throw new HubSdkError({
|
|
1509
|
+
code: "HUB_CONFIG_MISSING",
|
|
1510
|
+
message: "Invalid application authorization response"
|
|
1223
1511
|
});
|
|
1512
|
+
return {
|
|
1513
|
+
accessToken: body.access_token,
|
|
1514
|
+
expiresIn: body.expires_in,
|
|
1515
|
+
scopes: body.scope.split(" ").filter(Boolean)
|
|
1516
|
+
};
|
|
1224
1517
|
}
|
|
1225
|
-
async
|
|
1226
|
-
|
|
1518
|
+
async exchange(input) {
|
|
1519
|
+
const body = await this.token("/v1/apps/oauth/token", {
|
|
1520
|
+
grant_type: "authorization_code",
|
|
1521
|
+
code: input.code,
|
|
1522
|
+
redirect_uri: input.redirectUri,
|
|
1523
|
+
connection_id: input.connectionId,
|
|
1524
|
+
ttl_seconds: 60
|
|
1525
|
+
});
|
|
1526
|
+
const token = this.readToken(body);
|
|
1527
|
+
if (typeof body.grant_id !== "string" || !body.grant_id || body.connection_id !== input.connectionId) throw new HubSdkError({
|
|
1528
|
+
code: "HUB_CONFIG_MISSING",
|
|
1529
|
+
message: "Application connection did not match consent"
|
|
1530
|
+
});
|
|
1531
|
+
return {
|
|
1532
|
+
...token,
|
|
1533
|
+
grantId: body.grant_id,
|
|
1534
|
+
connectionId: input.connectionId
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
async mint(grantId) {
|
|
1538
|
+
if (!/^[A-Za-z0-9_-]{1,256}$/.test(grantId)) throw new Error("Invalid application grant");
|
|
1539
|
+
return this.readToken(await this.token(`/v1/apps/grants/${encodeURIComponent(grantId)}/mint-broker-token`, {
|
|
1540
|
+
grant_id: grantId,
|
|
1541
|
+
ttl_seconds: 60
|
|
1542
|
+
}));
|
|
1543
|
+
}
|
|
1544
|
+
async invoke(grantId, connectionId, actionPath, input) {
|
|
1545
|
+
const token = await this.mint(grantId);
|
|
1546
|
+
if (!token.scopes.includes(actionPath)) throw new HubSdkError({
|
|
1547
|
+
code: "HUB_POLICY_DENIED",
|
|
1548
|
+
message: "This action was not granted to the application"
|
|
1549
|
+
});
|
|
1550
|
+
return new HubClient({
|
|
1551
|
+
baseUrl: this.baseUrl,
|
|
1552
|
+
apiKey: token.accessToken,
|
|
1553
|
+
fetch: this.fetcher
|
|
1554
|
+
}).tools.invoke(actionPath, input, { connectionId });
|
|
1227
1555
|
}
|
|
1228
1556
|
};
|
|
1229
1557
|
//#endregion
|
|
@@ -1484,6 +1812,55 @@ function requestFailure(code, status, error, headers) {
|
|
|
1484
1812
|
};
|
|
1485
1813
|
}
|
|
1486
1814
|
//#endregion
|
|
1487
|
-
|
|
1815
|
+
//#region src/line-grants.ts
|
|
1816
|
+
function path(binding, suffix = "") {
|
|
1817
|
+
if (!binding.workspaceId || !binding.workspaceAgentId) throw new Error("A workspace and agent are required for a line grant");
|
|
1818
|
+
return `/v1/hub/line-grants/current${suffix}?${new URLSearchParams({
|
|
1819
|
+
workspaceId: binding.workspaceId,
|
|
1820
|
+
workspaceAgentId: binding.workspaceAgentId
|
|
1821
|
+
})}`;
|
|
1822
|
+
}
|
|
1823
|
+
/** Every call uses HubTransport's authHeaders, so one-use app broker tokens can be minted per request. */
|
|
1824
|
+
var HubLineGrantsClient = class extends HubTransport {
|
|
1825
|
+
current(binding) {
|
|
1826
|
+
return this.request(path(binding), { method: "GET" });
|
|
1827
|
+
}
|
|
1828
|
+
async line(binding) {
|
|
1829
|
+
return (await this.request(path(binding, "/line"), { method: "GET" })).line;
|
|
1830
|
+
}
|
|
1831
|
+
async attach(binding, input) {
|
|
1832
|
+
return (await this.request(path(binding, "/attachment"), jsonInit("PUT", input))).attachment;
|
|
1833
|
+
}
|
|
1834
|
+
detach(binding) {
|
|
1835
|
+
return this.request(path(binding, "/attachment"), { method: "DELETE" });
|
|
1836
|
+
}
|
|
1837
|
+
async threads(binding) {
|
|
1838
|
+
return (await this.request(path(binding, "/threads"), { method: "GET" })).threads;
|
|
1839
|
+
}
|
|
1840
|
+
async messages(binding, threadId) {
|
|
1841
|
+
if (!threadId || threadId.length > 256) throw new Error("A bounded line thread id is required");
|
|
1842
|
+
return (await this.request(path(binding, `/threads/${encodeURIComponent(threadId)}/messages`), { method: "GET" })).messages;
|
|
1843
|
+
}
|
|
1844
|
+
memberApplication(binding) {
|
|
1845
|
+
return this.request(path(binding, "/member-application"), { method: "GET" });
|
|
1846
|
+
}
|
|
1847
|
+
/**
|
|
1848
|
+
* Route the owner's texts to this app's callback; the incumbent attachment
|
|
1849
|
+
* stays. `replaceSelectionId` moves them from another app on the owner's
|
|
1850
|
+
* explicit choice.
|
|
1851
|
+
*/
|
|
1852
|
+
async selectApplication(binding, input) {
|
|
1853
|
+
return (await this.request(path(binding, "/member-application"), jsonInit("PUT", input))).selection;
|
|
1854
|
+
}
|
|
1855
|
+
/** Return the owner's texts to the incumbent attachment. */
|
|
1856
|
+
async clearApplication(binding, input) {
|
|
1857
|
+
await this.request(path(binding, "/member-application"), jsonInit("DELETE", input));
|
|
1858
|
+
}
|
|
1859
|
+
revoke(binding) {
|
|
1860
|
+
return this.request(path(binding), { method: "DELETE" });
|
|
1861
|
+
}
|
|
1862
|
+
};
|
|
1863
|
+
//#endregion
|
|
1864
|
+
export { HUB_API_KEY_ENV_VAR, HUB_CAPABILITY_TOKEN_ENV_VAR, HUB_URL_ENV_VAR, HubAllowancesClient, HubAppBrokerClient, HubApprovalsClient, HubAppsClient, HubAuditClient, HubChannelsClient, HubClient, HubConnectionsClient, HubEventDeliveryError, HubEventSubscriptionsClient, HubGithubAppClient, HubInboundWebhooksClient, HubKnowledgeClient, HubLineGrantsClient, HubLinesClient, HubManagedNumbersClient, HubPermissionsClient, HubSdkError, HubTokensClient, HubToolsClient, HubWorkflowsClient, authenticateHubEventRequest, deriveHubEventCallbackSecret, parseHubEventDelivery, redactHubValue, resolveHubAuth, resolveHubBaseUrl, verifyHubEventSignature };
|
|
1488
1865
|
|
|
1489
1866
|
//# sourceMappingURL=index.js.map
|