@trayai/helix-sdk 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +33 -0
- package/dist/broker/index.d.ts +73 -2
- package/dist/broker/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,20 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
8
8
|
The SDK and [`@trayai/helix-cli`](https://www.npmjs.com/package/@trayai/helix-cli) are
|
|
9
9
|
released together and share a version — install matching versions.
|
|
10
10
|
|
|
11
|
+
## 1.6.0
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Internal `@trayai/helix-sdk/broker` additions supporting the Helix CLI's new
|
|
16
|
+
`tray_list_authentication_templates` MCP tool. No changes to the SDK's public API
|
|
17
|
+
(`ctx.http`/`ctx.kv`/`ctx.files`, config, `/testing`).
|
|
18
|
+
|
|
19
|
+
### Documentation
|
|
20
|
+
|
|
21
|
+
- The README now has a "Connecting any API" guide: how to connect an API that is not in the
|
|
22
|
+
supported list using **HTTP Bearer Token**, **HTTP Basic Authentication** or **Custom Token
|
|
23
|
+
Authentication**, and what to enter in each form.
|
|
24
|
+
|
|
11
25
|
## 1.4.0
|
|
12
26
|
|
|
13
27
|
### Changed
|
package/README.md
CHANGED
|
@@ -114,6 +114,39 @@ Each method returns `{ status, body?, headers }`. An upstream non-2xx response i
|
|
|
114
114
|
- Redirects are not followed: a 3xx response is returned to your code with its `location` header, and following it is your decision. Plain `ctx.http` also stops auto-following redirects, but — unlike this authed client — it throws for a 3xx by default like any other non-2xx status; pass `{ throwHttpErrors: false }` to get it back as a value instead.
|
|
115
115
|
- An unknown alias throws `SdkError.unknownAlias` (the error lists the configured aliases).
|
|
116
116
|
|
|
117
|
+
### Connecting any API: the generic services
|
|
118
|
+
|
|
119
|
+
You are not limited to the services offered in the dashboard's service picker. If your API is not there and it authenticates with a token, an API key or a username and password, create the authentication against one of the generic services below, then call it exactly like any other alias with `ctx.http.authed(alias)`. The platform adds the credential to the request; the secret never reaches your code.
|
|
120
|
+
|
|
121
|
+
| If the API expects… | Pick |
|
|
122
|
+
|---------------------|------|
|
|
123
|
+
| `Authorization: Bearer <token>` | **HTTP Bearer Token** |
|
|
124
|
+
| A username and password (or an API token used as the password) | **HTTP Basic Authentication** |
|
|
125
|
+
| A token or API key in a header you name, or in the query string | **Custom Token Authentication** |
|
|
126
|
+
|
|
127
|
+
**How to create one**
|
|
128
|
+
|
|
129
|
+
1. Run `helix auth connect --new` (it opens the Helix dashboard for your workspace; use `--no-open` to print the link instead). In the dashboard, choose the generic service and fill in the form.
|
|
130
|
+
2. Back in the terminal the CLI finds the new authentication and writes the alias into `helix.config.ts` for you. (If you run it without a terminal, it only prints the link: connect the authentication afterwards with `helix auth connect` or `helix auth add <alias> <uuid>`.)
|
|
131
|
+
3. Call it: `await ctx.http.authed('my_api').get('https://api.vendor.com/v1/things')`.
|
|
132
|
+
|
|
133
|
+
**What to enter in the form**
|
|
134
|
+
|
|
135
|
+
*HTTP Bearer Token* and *HTTP Basic Authentication*: the token, or the username and password.
|
|
136
|
+
|
|
137
|
+
*Custom Token Authentication*
|
|
138
|
+
|
|
139
|
+
| Field | Value |
|
|
140
|
+
|-------|-------|
|
|
141
|
+
| Token | The API key or token |
|
|
142
|
+
| Location | `header` (the default) or `query` (the query string) |
|
|
143
|
+
| Location Value | The header name (for example `X-Api-Key`) or the query parameter (for example `api_key`) |
|
|
144
|
+
| Pin to domain | Optional but recommended: the only domain this credential may be sent to, for example `api.vendor.com` |
|
|
145
|
+
|
|
146
|
+
APIs that need OAuth 1.0a, a request signature (HMAC) or AWS Signature v4 are not available as generic services yet, and neither is OAuth 2.0 sign-in with token refresh: use the service's own entry if it is offered in the dashboard.
|
|
147
|
+
|
|
148
|
+
If the API answers `401`, check first that the authentication was created with the values and Location you expect.
|
|
149
|
+
|
|
117
150
|
### Signed S3 URLs — `s3Sign`
|
|
118
151
|
|
|
119
152
|
For AWS/S3 authentications, the authed client can mint a **presigned S3 URL** — a time-limited URL your code (or anyone you hand it to) uses against S3 directly, with no credentials attached:
|
package/dist/broker/index.d.ts
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
import { R as Region } from '../region-schema-COfWyGI9.js';
|
|
2
|
-
import 'zod';
|
|
2
|
+
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
type BrokerRegion = Region;
|
|
5
5
|
|
|
6
|
+
/** JSON-format strategy names — mirrors the credential broker's own
|
|
7
|
+
JsonTemplateStrategySchema. Hand-maintained: the two repos share no build
|
|
8
|
+
dependency, so this is intentionally duplicated rather than imported. */
|
|
9
|
+
declare const JSON_TEMPLATE_STRATEGIES: readonly ["bearer", "api-key-header", "api-key-query", "basic", "oauth1", "aws-sigv4", "hmac", "custom"];
|
|
10
|
+
type JsonTemplateStrategy = (typeof JSON_TEMPLATE_STRATEGIES)[number];
|
|
11
|
+
declare const TemplatesResponseSchema: z.ZodObject<{
|
|
12
|
+
templates: z.ZodArray<z.ZodObject<{
|
|
13
|
+
serviceName: z.ZodString;
|
|
14
|
+
serviceVersion: z.ZodNumber;
|
|
15
|
+
authenticationType: z.ZodString;
|
|
16
|
+
strategy: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
serviceName: string;
|
|
19
|
+
serviceVersion: number;
|
|
20
|
+
authenticationType: string;
|
|
21
|
+
strategy?: string | undefined;
|
|
22
|
+
}, {
|
|
23
|
+
serviceName: string;
|
|
24
|
+
serviceVersion: number;
|
|
25
|
+
authenticationType: string;
|
|
26
|
+
strategy?: string | undefined;
|
|
27
|
+
}>, "many">;
|
|
28
|
+
}, "strip", z.ZodTypeAny, {
|
|
29
|
+
templates: {
|
|
30
|
+
serviceName: string;
|
|
31
|
+
serviceVersion: number;
|
|
32
|
+
authenticationType: string;
|
|
33
|
+
strategy?: string | undefined;
|
|
34
|
+
}[];
|
|
35
|
+
}, {
|
|
36
|
+
templates: {
|
|
37
|
+
serviceName: string;
|
|
38
|
+
serviceVersion: number;
|
|
39
|
+
authenticationType: string;
|
|
40
|
+
strategy?: string | undefined;
|
|
41
|
+
}[];
|
|
42
|
+
}>;
|
|
43
|
+
type TemplatesResponse = z.infer<typeof TemplatesResponseSchema>;
|
|
44
|
+
|
|
6
45
|
interface BrokerDevCallParams {
|
|
7
46
|
/** Target Tray region — selects the broker base URL. */
|
|
8
47
|
env: BrokerRegion;
|
|
@@ -109,5 +148,37 @@ type S3SignDevCallResult = {
|
|
|
109
148
|
* explicitly.
|
|
110
149
|
*/
|
|
111
150
|
declare function callS3SignDev(params: S3SignDevCallParams): Promise<S3SignDevCallResult>;
|
|
151
|
+
interface TemplatesDevCallParams {
|
|
152
|
+
/** Target Tray region — selects the broker base URL. */
|
|
153
|
+
env: BrokerRegion;
|
|
154
|
+
/** Personal dev token (the user's local Tray login) sent as `Authorization: Bearer`. */
|
|
155
|
+
devToken: string;
|
|
156
|
+
timeoutMs?: number;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Result of a one-shot dev templates-discovery call.
|
|
160
|
+
* - `templates` — the registered (serviceName, serviceVersion,
|
|
161
|
+
* authenticationType, strategy?) keys.
|
|
162
|
+
* - `brokerError` — a broker-generated error.
|
|
163
|
+
*/
|
|
164
|
+
type TemplatesDevCallResult = {
|
|
165
|
+
kind: "templates";
|
|
166
|
+
templates: TemplatesResponse["templates"];
|
|
167
|
+
} | {
|
|
168
|
+
kind: "brokerError";
|
|
169
|
+
brokerStatus: number;
|
|
170
|
+
code?: string;
|
|
171
|
+
body: unknown;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Stateless, one-shot call to the credential broker's authentication-template
|
|
175
|
+
* discovery dev endpoint (`GET /private/v1/helix/authentications/templates/dev`).
|
|
176
|
+
*
|
|
177
|
+
* Factored out the same way `callS3SignDev`/`callBrokerDev` are, so CLI
|
|
178
|
+
* tooling (the `tray_list_authentication_templates` MCP tool) can list what
|
|
179
|
+
* auth mechanism the broker will apply for a given service without booting
|
|
180
|
+
* the dev server. Reads no module-global state.
|
|
181
|
+
*/
|
|
182
|
+
declare function callTemplatesDev(params: TemplatesDevCallParams): Promise<TemplatesDevCallResult>;
|
|
112
183
|
|
|
113
|
-
export { type BrokerDevCallParams, type BrokerDevCallResult, type BrokerRegion, type S3SignDevCallParams, type S3SignDevCallResult, type UpstreamResponse, callBrokerDev, callS3SignDev };
|
|
184
|
+
export { type BrokerDevCallParams, type BrokerDevCallResult, type BrokerRegion, type JsonTemplateStrategy, type S3SignDevCallParams, type S3SignDevCallResult, type TemplatesDevCallParams, type TemplatesDevCallResult, type UpstreamResponse, callBrokerDev, callS3SignDev, callTemplatesDev };
|
package/dist/broker/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{B as
|
|
1
|
+
import{A as u,B as d,D as p,F as m,G as c,H as k,I as g,J as b,j as l}from"../chunk-3T2WZMJJ.js";import{z as s}from"zod";function v(e,t){let r=`${l(e).hosts.api}/private/v1/helix/authentications/templates`;return t==="dev"?`${r}/dev`:r}var h=s.object({templates:s.array(s.object({serviceName:s.string(),serviceVersion:s.number().int(),authenticationType:s.string(),strategy:s.string().optional()}))}),S=3e4;async function y(e){let t=new Headers;for(let[n,T]of Object.entries(e.credentialHeaders))t.set(n,T);let r=await fetch(e.templatesUrl,{method:"GET",headers:t,redirect:"manual",signal:AbortSignal.timeout(e.timeoutMs??S)}),a=await r.text(),o=a;try{o=JSON.parse(a)}catch{}if(r.ok){let n=h.safeParse(o);return n.success?{kind:"templates",result:n.data}:{kind:"brokerError",status:r.status,message:"malformed templates-discovery response",body:o}}let i=u.safeParse(o);return i.success?{kind:"brokerError",status:r.status,code:i.data.error.code,message:i.data.error.message,body:o}:{kind:"brokerError",status:r.status,message:a||`templates-discovery request failed with status ${r.status}`,body:o}}async function R(e){let t=p({authenticationId:e.authenticationId,method:e.method,url:e.url,body:e.body,headers:e.headers,query:e.query}),r=await c({proxyUrl:d(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},request:t,timeoutMs:e.timeoutMs??m});return r.kind==="brokerError"?{kind:"brokerError",brokerStatus:r.status,code:r.code,body:r.body}:{kind:"upstream",upstream:r.response}}async function f(e){k(e.url);let t=await b({signUrl:g(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},body:{authenticationId:e.authenticationId,url:e.url,...e.method!==void 0?{method:e.method}:{},...e.expiresIn!==void 0?{expiresIn:e.expiresIn}:{}},timeoutMs:e.timeoutMs});return t.kind==="brokerError"?{kind:"brokerError",brokerStatus:t.status,code:t.code,body:t.body}:{kind:"signed",signed:t.result}}async function x(e){let t=await y({templatesUrl:v(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},timeoutMs:e.timeoutMs});return t.kind==="brokerError"?{kind:"brokerError",brokerStatus:t.status,code:t.code,body:t.body}:{kind:"templates",templates:t.result.templates}}export{R as callBrokerDev,f as callS3SignDev,x as callTemplatesDev};
|