@apteva/web-sdk 0.1.0 → 0.2.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 +13 -2
- package/README.md +9 -9
- package/dist/client.d.ts +3 -3
- package/dist/client.js +9 -9
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 — 2026-05-13
|
|
4
|
+
|
|
5
|
+
**Breaking**: class + interface renamed from `Apteve*` to `Apteva*` (typo fix — org name is `apteva`, not `apteve`).
|
|
6
|
+
|
|
7
|
+
- `ApteveClient` → `AptevaClient`
|
|
8
|
+
- `ApteveError` → `AptevaError`
|
|
9
|
+
- `ApteveClientOptions` → `AptevaClientOptions`
|
|
10
|
+
|
|
11
|
+
Same public surface, same behavior. Anyone on 0.1.0 (if any) renames the imports and is good.
|
|
12
|
+
|
|
13
|
+
|
|
3
14
|
## 0.1.0 — 2026-05-13
|
|
4
15
|
|
|
5
16
|
Initial release.
|
|
6
17
|
|
|
7
|
-
- `
|
|
18
|
+
- `AptevaClient` — base client with session-cookie + Bearer + `?api_key=` auth carriers, `credentials: include` for cross-origin cookie flow, configurable timeout, `onUnauthorized` hook.
|
|
8
19
|
- `client.auth` namespace — `register`, `login`, `logout`, `me`, `status`, `changePassword`, `listKeys`, `createKey`, `deleteKey`.
|
|
9
20
|
- `client.app(name)` — typed handle for any installed app: `get/post/put/patch/del` for HTTP routes + `tool(name, args)` for MCP calls. Generic type parameter for response shape.
|
|
10
21
|
- `unwrapMCP` — exposed standalone for callers that want to handle the JSON-RPC envelope themselves.
|
|
11
22
|
- Window helpers — `readAptevaInjection`, `pickKioskKey`, `pickBaseURL` for UIs hosted as static apps on apteva-server itself.
|
|
12
23
|
- `client.sseURL` + `client.app(...).mcpURL` builders for `EventSource` / `<iframe>` / external clients that can't go through `fetch`.
|
|
13
|
-
- `
|
|
24
|
+
- `AptevaError` with `.status`, `.body`, `.code`, `.isUnauthorized()`, `.isNotFound()`.
|
|
14
25
|
- 43 tests covering carriers, auth, app HTTP/MCP, envelope unwrap, window helpers.
|
package/README.md
CHANGED
|
@@ -18,9 +18,9 @@ npm install @apteva/web-sdk
|
|
|
18
18
|
## Quick start
|
|
19
19
|
|
|
20
20
|
```ts
|
|
21
|
-
import {
|
|
21
|
+
import { AptevaClient } from "@apteva/web-sdk";
|
|
22
22
|
|
|
23
|
-
const apteva = new
|
|
23
|
+
const apteva = new AptevaClient({
|
|
24
24
|
baseURL: "https://agents.example.com",
|
|
25
25
|
// Optional. Omit to rely on the session cookie (after auth.login).
|
|
26
26
|
apiKey: process.env.NEXT_PUBLIC_APTEVA_KEY,
|
|
@@ -47,7 +47,7 @@ The SDK sends `credentials: "include"` on every request, so a session cookie set
|
|
|
47
47
|
You can layer on an API key by setting `apiKey` in the constructor or calling `client.setApiKey(...)` at runtime. Bearer-wins-over-cookie on the wire.
|
|
48
48
|
|
|
49
49
|
```ts
|
|
50
|
-
const apteva = new
|
|
50
|
+
const apteva = new AptevaClient({
|
|
51
51
|
baseURL: "...",
|
|
52
52
|
apiKey: "sk-...", // optional
|
|
53
53
|
onUnauthorized: () => router.push("/login"), // fires once per 401
|
|
@@ -75,19 +75,19 @@ const result = await apteva.app("tables").tool<{ rows: Row[]; total: number }>(
|
|
|
75
75
|
);
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
If the MCP call returns a JSON-RPC error, the SDK throws `
|
|
78
|
+
If the MCP call returns a JSON-RPC error, the SDK throws `AptevaError(-1, message, code)` — same `catch` block as HTTP errors.
|
|
79
79
|
|
|
80
80
|
For lower-level usage, `client.callTool(appName, toolName, args)` and the standalone `unwrapMCP(envelope)` are both exported.
|
|
81
81
|
|
|
82
82
|
## Error handling
|
|
83
83
|
|
|
84
|
-
Every non-2xx response and every MCP error throws an `
|
|
84
|
+
Every non-2xx response and every MCP error throws an `AptevaError`:
|
|
85
85
|
|
|
86
86
|
```ts
|
|
87
87
|
try {
|
|
88
88
|
await apteva.app("crm").tool("contacts_get", { id: 999 });
|
|
89
89
|
} catch (err) {
|
|
90
|
-
if (err instanceof
|
|
90
|
+
if (err instanceof AptevaError) {
|
|
91
91
|
if (err.isUnauthorized()) ... // 401
|
|
92
92
|
if (err.isNotFound()) ... // 404
|
|
93
93
|
if (err.status === -1) ... // MCP-level error
|
|
@@ -96,16 +96,16 @@ try {
|
|
|
96
96
|
}
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
Network failures (no DNS, refused connection) surface as `
|
|
99
|
+
Network failures (no DNS, refused connection) surface as `AptevaError(0, "...")`. Timeouts surface as `AptevaError(0, "request timeout after Xms")`.
|
|
100
100
|
|
|
101
101
|
## Hosted on apteva-server itself
|
|
102
102
|
|
|
103
103
|
If your UI is installed as a `runtime.kind: static` app, apteva-server injects a config block. The SDK picks it up:
|
|
104
104
|
|
|
105
105
|
```ts
|
|
106
|
-
import {
|
|
106
|
+
import { AptevaClient, pickBaseURL, pickKioskKey } from "@apteva/web-sdk";
|
|
107
107
|
|
|
108
|
-
const apteva = new
|
|
108
|
+
const apteva = new AptevaClient({
|
|
109
109
|
baseURL: pickBaseURL(), // window.__APTEVA_APP__.api_base
|
|
110
110
|
apiKey: pickKioskKey(), // ?api_key=... > install config > undefined
|
|
111
111
|
});
|
package/dist/client.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare class
|
|
1
|
+
import type { AptevaClientOptions, AuthStatus, MCPCallResponse, User } from "./types.js";
|
|
2
|
+
export declare class AptevaClient {
|
|
3
3
|
private readonly baseURL;
|
|
4
4
|
private apiKey?;
|
|
5
5
|
private readonly fetchImpl;
|
|
6
6
|
private readonly onUnauthorized?;
|
|
7
7
|
private readonly timeoutMs;
|
|
8
|
-
constructor(opts:
|
|
8
|
+
constructor(opts: AptevaClientOptions);
|
|
9
9
|
setApiKey(key: string | undefined): void;
|
|
10
10
|
getApiKey(): string | undefined;
|
|
11
11
|
readonly auth: {
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AptevaError } from "./errors.js";
|
|
2
2
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
3
|
-
export class
|
|
3
|
+
export class AptevaClient {
|
|
4
4
|
baseURL;
|
|
5
5
|
apiKey;
|
|
6
6
|
fetchImpl;
|
|
@@ -138,20 +138,20 @@ export class ApteveClient {
|
|
|
138
138
|
if (timer)
|
|
139
139
|
clearTimeout(timer);
|
|
140
140
|
if (err instanceof Error && err.name === "AbortError") {
|
|
141
|
-
throw new
|
|
141
|
+
throw new AptevaError(0, `request timeout after ${this.timeoutMs}ms`);
|
|
142
142
|
}
|
|
143
|
-
throw new
|
|
143
|
+
throw new AptevaError(0, err instanceof Error ? err.message : String(err));
|
|
144
144
|
}
|
|
145
145
|
if (timer)
|
|
146
146
|
clearTimeout(timer);
|
|
147
147
|
if (res.status === 401) {
|
|
148
148
|
this.onUnauthorized?.();
|
|
149
149
|
const text = await readBody(res);
|
|
150
|
-
throw new
|
|
150
|
+
throw new AptevaError(401, text || "unauthorized");
|
|
151
151
|
}
|
|
152
152
|
if (!res.ok) {
|
|
153
153
|
const text = await readBody(res);
|
|
154
|
-
throw new
|
|
154
|
+
throw new AptevaError(res.status, text || res.statusText);
|
|
155
155
|
}
|
|
156
156
|
const ct = res.headers.get("Content-Type") ?? "";
|
|
157
157
|
if (res.status === 204)
|
|
@@ -172,13 +172,13 @@ async function readBody(res) {
|
|
|
172
172
|
}
|
|
173
173
|
// Strip the MCP JSON-RPC envelope so callers see the tool's natural
|
|
174
174
|
// return shape. Mirrors app-sdk/caller.go::CallAppResult. Three cases:
|
|
175
|
-
// 1. envelope.error → throw
|
|
175
|
+
// 1. envelope.error → throw AptevaError(-1, message, code)
|
|
176
176
|
// 2. envelope.result.content[0].text → JSON.parse(text), return it
|
|
177
177
|
// 3. envelope has neither (the platform already short-circuited an
|
|
178
178
|
// unwrapped response) → cast and return
|
|
179
179
|
export function unwrapMCP(env) {
|
|
180
180
|
if (env && env.error) {
|
|
181
|
-
throw new
|
|
181
|
+
throw new AptevaError(-1, env.error.message, env.error.code);
|
|
182
182
|
}
|
|
183
183
|
const text = env?.result?.content?.[0]?.text;
|
|
184
184
|
if (typeof text !== "string") {
|
|
@@ -188,7 +188,7 @@ export function unwrapMCP(env) {
|
|
|
188
188
|
return JSON.parse(text);
|
|
189
189
|
}
|
|
190
190
|
catch (err) {
|
|
191
|
-
throw new
|
|
191
|
+
throw new AptevaError(-1, `MCP response was not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
//# sourceMappingURL=client.js.map
|
package/dist/errors.d.ts
CHANGED
package/dist/errors.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
// network/transport failures, or -1 for JSON-RPC errors that came
|
|
4
4
|
// back inside a 200 envelope). body is the raw response body (text)
|
|
5
5
|
// or the JSON-RPC error.message — whichever was available.
|
|
6
|
-
export class
|
|
6
|
+
export class AptevaError extends Error {
|
|
7
7
|
status;
|
|
8
8
|
body;
|
|
9
9
|
code;
|
|
10
10
|
constructor(status, body, code) {
|
|
11
11
|
super(`HTTP ${status}: ${body}`);
|
|
12
|
-
this.name = "
|
|
12
|
+
this.name = "AptevaError";
|
|
13
13
|
this.status = status;
|
|
14
14
|
this.body = body;
|
|
15
15
|
this.code = code;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { AptevaClient, unwrapMCP } from "./client.js";
|
|
2
2
|
export type { AppHandle } from "./client.js";
|
|
3
|
-
export {
|
|
3
|
+
export { AptevaError } from "./errors.js";
|
|
4
4
|
export { readAptevaInjection, pickKioskKey, pickBaseURL, } from "./window.js";
|
|
5
|
-
export type {
|
|
5
|
+
export type { AptevaClientOptions, AuthCarrier, AuthBranding, AuthStatus, AptevaAppInjection, MCPCallRequest, MCPCallResponse, User, } from "./types.js";
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
1
|
+
export { AptevaClient, unwrapMCP } from "./client.js";
|
|
2
|
+
export { AptevaError } from "./errors.js";
|
|
3
3
|
export { readAptevaInjection, pickKioskKey, pickBaseURL, } from "./window.js";
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apteva/web-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Browser SDK for apteva-server. Handles auth (session cookie + API key + ?api_key=), wraps the /api/apps/<name>/* HTTP and MCP proxy, normalizes the MCP JSON-RPC envelope, and surfaces window.__APTEVA_APP__ when the UI is hosted on apteva-server itself. Framework-agnostic.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Apteva",
|