@conveo/conveo-sdk 0.3.1 → 0.4.1

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 CHANGED
@@ -57,6 +57,26 @@ user.email; // "you@conveo.ai"
57
57
  const res = await gatewayFetch("/postgrest/Organization?select=id,name", { user });
58
58
  ```
59
59
 
60
+ `gatewayFetch` can also call as the **app itself** instead of a user — for
61
+ gateway-fronted vendor APIs whose key lives at the gateway (HubSpot, Linear, …).
62
+ You authenticate with the app's Vercel OIDC identity; the gateway checks a Grant
63
+ and injects the vendor key on the upstream leg, so your app never holds it:
64
+
65
+ ```ts
66
+ // `service` targets the vendor API's own host; `identity: "app"` uses the
67
+ // app's VERCEL_OIDC_TOKEN as the bearer (the default when there's no `user`).
68
+ const res = await gatewayFetch("/crm/v3/objects/contacts?limit=3", {
69
+ identity: "app",
70
+ service: "hubspot",
71
+ });
72
+ ```
73
+
74
+ `service` resolves to `AGENTGATEWAY_SERVICE_<NAME>_URL` if set, else
75
+ `https://<name>.internal.conveo.ai` (override the suffix with
76
+ `AGENTGATEWAY_SERVICE_DOMAIN`). Install `@vercel/functions` for automatic
77
+ refresh of the short-lived OIDC token; without it the SDK reads
78
+ `VERCEL_OIDC_TOKEN` directly.
79
+
60
80
  The `user` you get back looks like this:
61
81
 
62
82
  ```ts
@@ -83,6 +103,70 @@ Want a full working example? See the
83
103
  [template app](https://github.com/conveo/agentgateway-template-app). Clone
84
104
  it and you're done.
85
105
 
106
+ ## Third-party SDKs through the gateway
107
+
108
+ `gatewayFetch({ service })` is the low-level way to reach a gateway-fronted vendor
109
+ API. For the common ones, these subpaths hand you the **official vendor SDK** already
110
+ pointed at the gateway and authenticated — no host, no token, no vendor key in your app:
111
+
112
+ | Import | Returns | Vendor SDK |
113
+ |---|---|---|
114
+ | `@conveo/conveo-sdk/linear` | `getLinearClient()` → `LinearClient` | `@linear/sdk` |
115
+ | `@conveo/conveo-sdk/hubspot` | `getHubspotClient()` → HubSpot `Client` | `@hubspot/api-client` |
116
+ | `@conveo/conveo-sdk/postgrest` | `postgrest()` / `postgrestWithCount()` | none (typed helper) |
117
+
118
+ **Prerequisites (one-time):**
119
+
120
+ 1. On the Vercel project: **Settings → Functions → OIDC Federation = ON** (Vercel then
121
+ injects a fresh `VERCEL_OIDC_TOKEN` into every server invocation). Install
122
+ `@vercel/functions` for automatic token refresh.
123
+ 2. The app must be **granted** each route — the gateway is fail-closed. Onboarding adds
124
+ an `Identity` + `Grant` for your Vercel project in `conveo/agentgateway`; until then,
125
+ calls return `401`.
126
+ 3. Install the vendor SDK you use (optional peer deps): `pnpm add @linear/sdk` /
127
+ `pnpm add @hubspot/api-client`. PostgREST needs none.
128
+
129
+ **Linear / HubSpot** — build the client **per request** (the OIDC token rotates) and use
130
+ the native SDK:
131
+
132
+ ```ts
133
+ import { getLinearClient } from "@conveo/conveo-sdk/linear";
134
+ import { getHubspotClient } from "@conveo/conveo-sdk/hubspot";
135
+
136
+ export async function GET() {
137
+ const linear = await getLinearClient();
138
+ const issues = await linear.issues({ first: 10 });
139
+
140
+ const hs = await getHubspotClient();
141
+ const deals = await hs.crm.deals.basicApi.getPage(10);
142
+
143
+ return Response.json({ issues: issues.nodes, deals: deals.results });
144
+ }
145
+ ```
146
+
147
+ **PostgREST** — a typed helper returning a result union (never throws on a bad status):
148
+
149
+ ```ts
150
+ import { postgrest } from "@conveo/conveo-sdk/postgrest";
151
+
152
+ const res = await postgrest<Org[]>("Organization?select=id,name&limit=100");
153
+ if (!res.ok) return Response.json({ error: res.kind }, { status: res.status });
154
+ return Response.json(res.data); // res.kind: ok | unauthenticated | unauthorized | unreachable | error
155
+ ```
156
+
157
+ Notes:
158
+
159
+ - **Server-side only** — these need the Vercel OIDC token. Never call from a client component.
160
+ - **Call the factory per request**, inside your handler — never cache a client at module scope.
161
+ - **App identity, not user identity** — the gateway injects a *shared* upstream credential
162
+ (e.g. Linear writes appear as the shared app actor, not the signed-in person).
163
+ - **Hosts** follow the same `service` convention as `gatewayFetch`: `linear`/`hubspot`
164
+ resolve to `https://<name>.internal.conveo.ai` (override with
165
+ `AGENTGATEWAY_SERVICE_<NAME>_URL` / `AGENTGATEWAY_SERVICE_DOMAIN`, or a per-call
166
+ `baseUrl`). PostgREST is a path on the API base (`AGENTGATEWAY_API_URL`).
167
+ - **Errors:** `401` = OIDC off, wrong project slug, or route not granted; `403` = the
168
+ upstream credential's scopes don't cover the call (a gateway-side change).
169
+
86
170
  ## How it works
87
171
 
88
172
  ![How it works](docs/how-it-works.svg)
@@ -117,6 +201,9 @@ The SDK is a pure, environment-free core with thin adapters per runtime:
117
201
  | `…/vercel` | root `middleware.ts` of any non-Next Vercel app (Vite SPA etc.) |
118
202
  | `…/supabase` | `requireGatewayUser(req)` in Deno edge functions |
119
203
  | `…/server` | `getGatewayUser()`, `gatewayFetch()` in Next server code |
204
+ | `…/linear` | `getLinearClient()` — Linear via the gateway ([integrations](#third-party-sdks-through-the-gateway)) |
205
+ | `…/hubspot` | `getHubspotClient()` — HubSpot via the gateway |
206
+ | `…/postgrest` | `postgrest()` — Conveo Postgres replica via the gateway |
120
207
 
121
208
  ### What the middleware verifies
122
209
 
@@ -138,6 +225,8 @@ conveo-realm user tokens carry no `aud` claim today.
138
225
  | `AGENTGATEWAY_SIGNIN_URL` | — | Browser 302 target; unset → always 401 |
139
226
  | `AGENTGATEWAY_AUTH_MODE` | `required` | `optional` verifies but never rejects |
140
227
  | `AGENTGATEWAY_API_URL` / `_MCP_URL` | gateway prod hosts | `gatewayFetch` bases |
228
+ | `AGENTGATEWAY_SERVICE_<NAME>_URL` | `https://<name>.<domain>` | Override a `gatewayFetch({ service })` host (e.g. `AGENTGATEWAY_SERVICE_HUBSPOT_URL`) |
229
+ | `AGENTGATEWAY_SERVICE_DOMAIN` | `internal.conveo.ai` | Suffix for unresolved `service` hosts |
141
230
  | `AGENTGATEWAY_DEV_TOKEN` / `_DEV_MOCK_USER` | — | Local dev only; honored only when `NODE_ENV` or `VERCEL_ENV` is `development` |
142
231
 
143
232
  Code options: `createGatewayProxy({ publicPaths: ["/api/health"], ... })` —
@@ -0,0 +1,65 @@
1
+ export interface IntegrationOptions {
2
+ /**
3
+ * Override the resolved gateway host (full base URL). Precedence: this >
4
+ * `AGENTGATEWAY_SERVICE_<NAME>_URL` env > `https://<name>.<domain>` convention.
5
+ */
6
+ baseUrl?: string;
7
+ /**
8
+ * Supply the bearer token yourself. Escape hatch for non-Vercel runtimes and
9
+ * tests; by default the app's Vercel OIDC token is fetched fresh per call.
10
+ */
11
+ getToken?: () => Promise<string> | string;
12
+ /**
13
+ * Inject a `fetch` implementation. Used by the custom-fetch integrations and the
14
+ * raw helpers (e.g. tests). Ignored by static-token vendor SDKs (Linear, HubSpot)
15
+ * that take the token at construction and use their own transport.
16
+ */
17
+ fetch?: typeof fetch;
18
+ }
19
+ /** Resolve the bearer token: the caller's `getToken`, else the app's Vercel OIDC token. */
20
+ export declare function resolveToken(opts?: IntegrationOptions): Promise<string>;
21
+ /**
22
+ * A `fetch` that attaches `Authorization: Bearer <token>` — but only to the gateway
23
+ * origin. Handed to custom-fetch vendor SDKs (e.g. Notion) and used by the raw
24
+ * helpers. Refuses any other origin so a misconfigured `baseUrl` can't leak the token.
25
+ */
26
+ export declare function createGatewayFetch(allowedHost: string, opts?: IntegrationOptions): typeof fetch;
27
+ /**
28
+ * Typed result for the raw (non-vendor-SDK) helpers. Distinguishes a gateway
29
+ * rejection (401, your OIDC token / grant) from an upstream scope error (403) from
30
+ * a network failure (`unreachable`) — so callers never fabricate data on failure.
31
+ */
32
+ export type GatewayResult<T> = {
33
+ ok: true;
34
+ kind: "ok";
35
+ status: number;
36
+ data: T;
37
+ } | {
38
+ ok: false;
39
+ kind: "unauthenticated";
40
+ status: number;
41
+ error: string;
42
+ } | {
43
+ ok: false;
44
+ kind: "unauthorized";
45
+ status: number;
46
+ error: string;
47
+ } | {
48
+ ok: false;
49
+ kind: "unreachable";
50
+ status: 0;
51
+ error: string;
52
+ } | {
53
+ ok: false;
54
+ kind: "error";
55
+ status: number;
56
+ error: string;
57
+ };
58
+ /** Map a `Response` to a {@link GatewayResult}. Assumes a JSON body on success. */
59
+ export declare function toGatewayResult<T>(response: Response): Promise<GatewayResult<T>>;
60
+ /**
61
+ * Fetch a gateway JSON endpoint and map it to a {@link GatewayResult}. A network
62
+ * failure (`fetch` throwing a `TypeError`) becomes `unreachable`; config/origin/token
63
+ * errors propagate (they are programmer errors, not request outcomes).
64
+ */
65
+ export declare function gatewayJson<T>(url: string, init: RequestInit, opts?: IntegrationOptions): Promise<GatewayResult<T>>;
@@ -0,0 +1 @@
1
+ import{getAppToken as c}from"../internal.js";function u(t){return Promise.resolve(t?.getToken?t.getToken():c(process.env))}function f(t,r){const o=r?.fetch??fetch,n=new URL(t).origin;return(async(e,a)=>{const s=e instanceof URL?e:new URL(typeof e=="string"?e:e.url);if(s.origin!==n)throw new Error(`gateway fetch refused: ${s.origin} is not the gateway origin ${n}`);const i=new Headers(a?.headers??(typeof e=="object"&&"headers"in e?e.headers:void 0));return i.set("authorization",`Bearer ${await u(r)}`),o(s,{...a,headers:i})})}async function h(t){try{return await t.text()}catch{return""}}async function d(t){if(t.ok)return{ok:!0,kind:"ok",status:t.status,data:await t.json()};const r=await h(t);return t.status===401?{ok:!1,kind:"unauthenticated",status:401,error:r}:t.status===403?{ok:!1,kind:"unauthorized",status:403,error:r}:{ok:!1,kind:"error",status:t.status,error:r}}async function k(t,r,o){const n=f(t,o);let e;try{e=await n(t,r)}catch(a){if(a instanceof TypeError)return{ok:!1,kind:"unreachable",status:0,error:a.message};throw a}return d(e)}export{f as createGatewayFetch,k as gatewayJson,u as resolveToken,d as toGatewayResult};
@@ -0,0 +1,24 @@
1
+ /**
2
+ * HubSpot via the agent gateway, using the official `@hubspot/api-client`.
3
+ *
4
+ * The app never holds a HubSpot key: the client's `basePath` is the gateway
5
+ * (`hubspot.internal.conveo.ai`, paths map 1:1 to `api.hubapi.com`) and its
6
+ * `accessToken` is the app's Vercel OIDC token; the gateway validates it and swaps
7
+ * in the shared HubSpot private-app token upstream.
8
+ *
9
+ * ```ts
10
+ * import { getHubspotClient } from "@conveo/conveo-sdk/hubspot";
11
+ *
12
+ * export async function GET() {
13
+ * const hs = await getHubspotClient(); // build per request — token rotates
14
+ * const page = await hs.crm.deals.basicApi.getPage(10);
15
+ * return Response.json(page.results);
16
+ * }
17
+ * ```
18
+ *
19
+ * Static-token bucket: `@hubspot/api-client` has no custom-fetch seam and bakes the
20
+ * token in at construction, so build a fresh client per request. SERVER-SIDE ONLY.
21
+ */
22
+ import { Client } from "@hubspot/api-client";
23
+ import { type IntegrationOptions } from "./_shared.js";
24
+ export declare function getHubspotClient(opts?: IntegrationOptions): Promise<Client>;
@@ -0,0 +1 @@
1
+ import{Client as r}from"@hubspot/api-client";import{resolveServiceUrl as o}from"../internal.js";import{resolveToken as t}from"./_shared.js";async function a(e){return new r({basePath:e?.baseUrl??o("hubspot",process.env),accessToken:await t(e)})}export{a as getHubspotClient};
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Linear via the agent gateway, using the official `@linear/sdk`.
3
+ *
4
+ * The app never holds a Linear token: the client is pointed at the gateway
5
+ * (`linear.internal.conveo.ai/graphql`) and authenticates with the app's Vercel
6
+ * OIDC token; the gateway validates it and attaches the shared Linear app token
7
+ * upstream (writes show as the shared app actor, not a person).
8
+ *
9
+ * ```ts
10
+ * import { getLinearClient } from "@conveo/conveo-sdk/linear";
11
+ *
12
+ * export async function GET() {
13
+ * const linear = await getLinearClient(); // build per request — token rotates
14
+ * const issues = await linear.issues({ first: 10 });
15
+ * return Response.json(issues.nodes);
16
+ * }
17
+ * ```
18
+ *
19
+ * Static-token bucket: `@linear/sdk` bakes the token in at construction, so build
20
+ * a fresh client per request. SERVER-SIDE ONLY (needs the Vercel OIDC token).
21
+ */
22
+ import { LinearClient } from "@linear/sdk";
23
+ import { type IntegrationOptions } from "./_shared.js";
24
+ export declare function getLinearClient(opts?: IntegrationOptions): Promise<LinearClient>;
@@ -0,0 +1 @@
1
+ import{LinearClient as n}from"@linear/sdk";import{resolveServiceUrl as o}from"../internal.js";import{resolveToken as i}from"./_shared.js";async function s(e){const r=e?.baseUrl??`${o("linear",process.env)}/graphql`;return new n({apiUrl:r,accessToken:await i(e)})}export{s as getLinearClient};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * PostgREST (the Conveo central Postgres replica) via the agent gateway.
3
+ *
4
+ * No vendor SDK — a thin typed helper over the gateway. The app authenticates with
5
+ * its Vercel OIDC token; the gateway validates it and forwards to PostgREST under
6
+ * the `/postgrest` mount on the API base (the prefix is stripped before PostgREST
7
+ * sees it). Table names are PascalCase.
8
+ *
9
+ * Unlike Linear/HubSpot (host-based `service` routes), PostgREST is a path under the
10
+ * API base — so it resolves from `AGENTGATEWAY_API_URL` (default `gateway.ops.conveo.ai`),
11
+ * matching `gatewayFetch`'s `base: "api"`.
12
+ *
13
+ * ```ts
14
+ * import { postgrest } from "@conveo/conveo-sdk/postgrest";
15
+ *
16
+ * const res = await postgrest<Org[]>("Organization?select=id,name&limit=100");
17
+ * if (!res.ok) return Response.json({ error: res.kind }, { status: res.status });
18
+ * return Response.json(res.data);
19
+ * ```
20
+ */
21
+ import { type GatewayResult, type IntegrationOptions } from "./_shared.js";
22
+ /**
23
+ * Run a PostgREST query (e.g. `"Organization?select=id,name&limit=100"`). Pass
24
+ * `init` for writes (`method`, `body`, …).
25
+ */
26
+ export declare function postgrest<T>(query: string, init?: RequestInit, opts?: IntegrationOptions): Promise<GatewayResult<T>>;
27
+ /**
28
+ * Run a PostgREST query and also return the exact total row count (sends
29
+ * `Prefer: count=exact` and parses the `Content-Range` response header). `total`
30
+ * is `null` if PostgREST didn't return a count.
31
+ */
32
+ export declare function postgrestWithCount<T>(query: string, init?: RequestInit, opts?: IntegrationOptions): Promise<GatewayResult<{
33
+ rows: T;
34
+ total: number | null;
35
+ }>>;
@@ -0,0 +1 @@
1
+ import{createGatewayFetch as p,gatewayJson as f}from"./_shared.js";const h="https://gateway.ops.conveo.ai";function c(a,r){const e=(r?.baseUrl??`${process.env.AGENTGATEWAY_API_URL??h}/postgrest`).replace(/\/+$/,""),n=a.replace(/^\/?(postgrest\/)?/,"");return`${e}/${n}`}function k(a,r={},e){return f(c(a,e),r,e)}async function g(a,r={},e){const n=c(a,e),i=p(n,e),o=new Headers(r.headers);o.set("prefer","count=exact");let t;try{t=await i(n,{...r,headers:o})}catch(s){if(s instanceof TypeError)return{ok:!1,kind:"unreachable",status:0,error:s.message};throw s}if(!t.ok){const s=await t.text().catch(()=>"");return t.status===401?{ok:!1,kind:"unauthenticated",status:401,error:s}:t.status===403?{ok:!1,kind:"unauthorized",status:403,error:s}:{ok:!1,kind:"error",status:t.status,error:s}}const l=await t.json(),u=Number(t.headers.get("content-range")?.split("/")[1]);return{ok:!0,kind:"ok",status:t.status,data:{rows:l,total:Number.isFinite(u)?u:null}}}export{k as postgrest,g as postgrestWithCount};
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Internal, runtime-agnostic gateway helpers shared by `./server` and the
3
+ * third-party integrations (`./linear`, `./hubspot`, `./postgrest`).
4
+ *
5
+ * Deliberately free of `next` (and any runtime-specific) imports so the
6
+ * integration subpaths can reuse the same host/token resolution without dragging
7
+ * Next.js into a non-Next consumer.
8
+ */
9
+ /**
10
+ * Resolve a host-based, gateway-fronted vendor API to its base URL. Honours
11
+ * `AGENTGATEWAY_SERVICE_<NAME>_URL`, else `https://<name>.<AGENTGATEWAY_SERVICE_DOMAIN
12
+ * ?? internal.conveo.ai>`.
13
+ */
14
+ export declare function resolveServiceUrl(service: string, env: NodeJS.ProcessEnv): string;
15
+ /**
16
+ * The app's own identity token (Vercel OIDC). Prefers `getVercelOidcToken()` from
17
+ * `@vercel/functions` — it refreshes the short-lived token in dev and reads the
18
+ * runtime token in prod — but that's an OPTIONAL peer dep, so we fall back to the
19
+ * raw `VERCEL_OIDC_TOKEN` env var when it isn't installed.
20
+ */
21
+ export declare function getAppToken(env: NodeJS.ProcessEnv): Promise<string>;
@@ -0,0 +1 @@
1
+ const n=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;function a(e,t){if(!n.test(e))throw new Error(`invalid service name "${e}" \u2014 expected a lowercase DNS label (letters, digits, dashes)`);const r=t[`AGENTGATEWAY_SERVICE_${e.toUpperCase().replace(/-/g,"_")}_URL`];if(r)return r;const o=t.AGENTGATEWAY_SERVICE_DOMAIN??"internal.conveo.ai";return`https://${e}.${o}`}async function c(e){try{const{getVercelOidcToken:r}=await import("@vercel/functions/oidc"),o=await r();if(o)return o}catch{}const t=e.VERCEL_OIDC_TOKEN;if(!t)throw new Error("VERCEL_OIDC_TOKEN is not available \u2014 enable OIDC federation on the Vercel project (or `vercel env pull` for local dev). Install @vercel/functions for automatic token refresh.");return t}export{c as getAppToken,a as resolveServiceUrl};
package/dist/server.d.ts CHANGED
@@ -19,12 +19,33 @@ export interface GatewayFetchOptions extends RequestInit {
19
19
  identity?: "user" | "app";
20
20
  /** Which gateway host to target. Default `api` (gateway.ops); `mcp` for MCP/LLM routes. */
21
21
  base?: keyof typeof DEFAULT_BASES;
22
+ /**
23
+ * A host-based, gateway-fronted vendor API to target instead of `base` —
24
+ * e.g. `"hubspot"` or `"linear"`. These live on their own hostname (the
25
+ * gateway rewrites the Host to the real vendor and injects the vendor key
26
+ * server-side), not on a path under gateway.ops, so they can't be reached
27
+ * with `base`. Resolves to `AGENTGATEWAY_SERVICE_<NAME>_URL` if set, else
28
+ * `https://<name>.<AGENTGATEWAY_SERVICE_DOMAIN ?? internal.conveo.ai>`.
29
+ *
30
+ * Such calls are authorized as the **app** (the gateway Grant is on the
31
+ * Vercel deployment), so they default to `identity: "app"`. Mutually
32
+ * exclusive with `base`.
33
+ */
34
+ service?: string;
22
35
  }
23
36
  /**
24
37
  * Fetch a gateway route with the right credential:
25
38
  *
26
39
  * ```ts
27
- * const res = await gatewayFetch("/postgrest/Organization?select=id,name&limit=3", { user });
40
+ * // on behalf of the signed-in user (their forwarded token):
41
+ * await gatewayFetch("/postgrest/Organization?select=id,name&limit=3", { user });
42
+ *
43
+ * // as the app itself, against a gateway-fronted vendor API (HubSpot): the
44
+ * // gateway injects HubSpot's key server-side — the app never holds it.
45
+ * await gatewayFetch("/crm/v3/objects/contacts?limit=3", {
46
+ * identity: "app",
47
+ * service: "hubspot",
48
+ * });
28
49
  * ```
29
50
  */
30
51
  export declare function gatewayFetch(path: string, options?: GatewayFetchOptions): Promise<Response>;
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- import{headers as E}from"next/headers";import{configFromEnv as d,isDevelopment as f}from"./adapters/env.js";import{GatewayAuthError as h,IDENTITY_HEADERS as m}from"./core/types.js";import{createVerifier as l}from"./core/verify.js";let w;function v(){return w??=l(d(process.env)),w}async function k(){const e=(await E()).get(m.token);if(!e){const t=process.env.AGENTGATEWAY_DEV_MOCK_USER;if(t&&f(process.env)){const r=t.toLowerCase();return{sub:"dev-mock-user",email:r,emailVerified:!0,token:"",claims:{sub:"dev-mock-user",email:r}}}throw new h("unauthenticated","no gateway user on this request \u2014 public path, optional auth, or middleware not applied")}return v().verifyToken(e)}const y={api:"https://gateway.ops.conveo.ai",mcp:"https://mcp.ops.conveo.ai"};async function G(s,e={}){const{user:t,identity:r=e.user?"user":"app",base:c="api",...u}=e,n=process.env,o=(c==="mcp"?n.AGENTGATEWAY_MCP_URL:n.AGENTGATEWAY_API_URL)??y[c],a=new URL(s,o.endsWith("/")?o:`${o}/`);if(a.origin!==new URL(o).origin)throw new Error(`gatewayFetch path must stay on the gateway origin (resolved to ${a.origin})`);const i=new Headers(u.headers);if(r==="user"){if(!t?.token)throw new h("unauthenticated",'gatewayFetch with identity "user" needs a verified user with a token (mock users have none)');i.set("authorization",`Bearer ${t.token}`)}else{const p=n.VERCEL_OIDC_TOKEN;if(!p)throw new Error("VERCEL_OIDC_TOKEN is not available \u2014 enable OIDC federation on the Vercel project (or `vercel env pull` for local dev)");i.set("authorization",`Bearer ${p}`)}return fetch(a,{...u,headers:i})}import{GatewayAuthError as L}from"./core/types.js";export{L as GatewayAuthError,G as gatewayFetch,k as getGatewayUser};
1
+ import{headers as f}from"next/headers";import{configFromEnv as m,isDevelopment as v}from"./adapters/env.js";import{GatewayAuthError as w,IDENTITY_HEADERS as E}from"./core/types.js";import{createVerifier as l}from"./core/verify.js";import{getAppToken as g,resolveServiceUrl as y}from"./internal.js";let d;function A(){return d??=l(m(process.env)),d}async function F(){const t=(await f()).get(E.token);if(!t){const r=process.env.AGENTGATEWAY_DEV_MOCK_USER;if(r&&v(process.env)){const o=r.toLowerCase();return{sub:"dev-mock-user",email:o,emailVerified:!0,token:"",claims:{sub:"dev-mock-user",email:o}}}throw new w("unauthenticated","no gateway user on this request \u2014 public path, optional auth, or middleware not applied")}return A().verifyToken(t)}const k={api:"https://gateway.ops.conveo.ai",mcp:"https://mcp.ops.conveo.ai"};async function L(s,t={}){const{user:r,identity:o=t.user?"user":"app",base:c,service:u,...h}=t,n=process.env;let e;if(u!==void 0){if(c!==void 0)throw new Error("gatewayFetch: pass either `service` or `base`, not both");e=y(u,n)}else{const p=c??"api";e=(p==="mcp"?n.AGENTGATEWAY_MCP_URL:n.AGENTGATEWAY_API_URL)??k[p]}const i=new URL(s,e.endsWith("/")?e:`${e}/`);if(i.origin!==new URL(e).origin)throw new Error(`gatewayFetch path must stay on the gateway origin (resolved to ${i.origin})`);const a=new Headers(h.headers);if(o==="user"){if(!r?.token)throw new w("unauthenticated",'gatewayFetch with identity "user" needs a verified user with a token (mock users have none)');a.set("authorization",`Bearer ${r.token}`)}else a.set("authorization",`Bearer ${await g(n)}`);return fetch(i,{...h,headers:a})}import{GatewayAuthError as H}from"./core/types.js";export{H as GatewayAuthError,L as gatewayFetch,F as getGatewayUser};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conveo/conveo-sdk",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "SDK for Conveo apps behind the agent gateway: drop-in auth middleware (Next.js / Vercel / Supabase), server helpers, and a dev-token CLI.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -39,6 +39,18 @@
39
39
  "./server": {
40
40
  "types": "./dist/server.d.ts",
41
41
  "default": "./dist/server.js"
42
+ },
43
+ "./linear": {
44
+ "types": "./dist/integrations/linear.d.ts",
45
+ "default": "./dist/integrations/linear.js"
46
+ },
47
+ "./hubspot": {
48
+ "types": "./dist/integrations/hubspot.d.ts",
49
+ "default": "./dist/integrations/hubspot.js"
50
+ },
51
+ "./postgrest": {
52
+ "types": "./dist/integrations/postgrest.d.ts",
53
+ "default": "./dist/integrations/postgrest.js"
42
54
  }
43
55
  },
44
56
  "bin": {
@@ -56,10 +68,18 @@
56
68
  "jose": "^6.2.3"
57
69
  },
58
70
  "peerDependencies": {
71
+ "@hubspot/api-client": ">=10",
72
+ "@linear/sdk": ">=30",
59
73
  "@vercel/functions": ">=2",
60
74
  "next": ">=14"
61
75
  },
62
76
  "peerDependenciesMeta": {
77
+ "@hubspot/api-client": {
78
+ "optional": true
79
+ },
80
+ "@linear/sdk": {
81
+ "optional": true
82
+ },
63
83
  "@vercel/functions": {
64
84
  "optional": true
65
85
  },
@@ -68,6 +88,8 @@
68
88
  }
69
89
  },
70
90
  "devDependencies": {
91
+ "@hubspot/api-client": "^14.0.0",
92
+ "@linear/sdk": "^87.0.0",
71
93
  "@types/node": "^24.0.0",
72
94
  "@vercel/functions": "^3.7.1",
73
95
  "esbuild": "^0.28.1",