@codespar/sdk 0.11.0 → 0.12.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.
Files changed (73) hide show
  1. package/README.md +69 -0
  2. package/dist/__tests__/abort.test.d.ts +2 -0
  3. package/dist/__tests__/abort.test.d.ts.map +1 -0
  4. package/dist/__tests__/abort.test.js +70 -0
  5. package/dist/__tests__/abort.test.js.map +1 -0
  6. package/dist/__tests__/api-client.test.d.ts +7 -0
  7. package/dist/__tests__/api-client.test.d.ts.map +1 -0
  8. package/dist/__tests__/api-client.test.js +286 -0
  9. package/dist/__tests__/api-client.test.js.map +1 -0
  10. package/dist/__tests__/close-timeout.test.d.ts +2 -0
  11. package/dist/__tests__/close-timeout.test.d.ts.map +1 -0
  12. package/dist/__tests__/close-timeout.test.js +57 -0
  13. package/dist/__tests__/close-timeout.test.js.map +1 -0
  14. package/dist/__tests__/codespar.test.js +11 -0
  15. package/dist/__tests__/codespar.test.js.map +1 -1
  16. package/dist/__tests__/connections-timeout.test.d.ts +2 -0
  17. package/dist/__tests__/connections-timeout.test.d.ts.map +1 -0
  18. package/dist/__tests__/connections-timeout.test.js +58 -0
  19. package/dist/__tests__/connections-timeout.test.js.map +1 -0
  20. package/dist/__tests__/fetch-timeout.test.d.ts +2 -0
  21. package/dist/__tests__/fetch-timeout.test.d.ts.map +1 -0
  22. package/dist/__tests__/fetch-timeout.test.js +137 -0
  23. package/dist/__tests__/fetch-timeout.test.js.map +1 -0
  24. package/dist/__tests__/openapi-snapshot.test.d.ts +13 -0
  25. package/dist/__tests__/openapi-snapshot.test.d.ts.map +1 -0
  26. package/dist/__tests__/openapi-snapshot.test.js +79 -0
  27. package/dist/__tests__/openapi-snapshot.test.js.map +1 -0
  28. package/dist/__tests__/shop.test.js +1 -1
  29. package/dist/__tests__/shop.test.js.map +1 -1
  30. package/dist/__tests__/stream-timeout.test.d.ts +2 -0
  31. package/dist/__tests__/stream-timeout.test.d.ts.map +1 -0
  32. package/dist/__tests__/stream-timeout.test.js +335 -0
  33. package/dist/__tests__/stream-timeout.test.js.map +1 -0
  34. package/dist/api/client.d.ts +56 -0
  35. package/dist/api/client.d.ts.map +1 -0
  36. package/dist/api/client.js +221 -0
  37. package/dist/api/client.js.map +1 -0
  38. package/dist/api/types.d.ts +110 -0
  39. package/dist/api/types.d.ts.map +1 -0
  40. package/dist/api/types.js +10 -0
  41. package/dist/api/types.js.map +1 -0
  42. package/dist/errors.d.ts +5 -0
  43. package/dist/errors.d.ts.map +1 -1
  44. package/dist/errors.js +9 -0
  45. package/dist/errors.js.map +1 -1
  46. package/dist/generated/openapi.d.ts +22004 -0
  47. package/dist/generated/openapi.d.ts.map +1 -0
  48. package/dist/generated/openapi.js +2 -0
  49. package/dist/generated/openapi.js.map +1 -0
  50. package/dist/generated/operations.d.ts +1084 -0
  51. package/dist/generated/operations.d.ts.map +1 -0
  52. package/dist/generated/operations.js +225 -0
  53. package/dist/generated/operations.js.map +1 -0
  54. package/dist/index.d.ts +24 -4
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +32 -3
  57. package/dist/index.js.map +1 -1
  58. package/dist/internal/abort.d.ts +18 -0
  59. package/dist/internal/abort.d.ts.map +1 -0
  60. package/dist/internal/abort.js +42 -0
  61. package/dist/internal/abort.js.map +1 -0
  62. package/dist/internal/fetch.d.ts +23 -0
  63. package/dist/internal/fetch.d.ts.map +1 -0
  64. package/dist/internal/fetch.js +57 -0
  65. package/dist/internal/fetch.js.map +1 -0
  66. package/dist/session.d.ts +3 -2
  67. package/dist/session.d.ts.map +1 -1
  68. package/dist/session.js +339 -161
  69. package/dist/session.js.map +1 -1
  70. package/dist/types.d.ts +3 -0
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/types.js.map +1 -1
  73. package/package.json +7 -3
package/README.md CHANGED
@@ -158,6 +158,8 @@ const result = await loop(session, {
158
158
  | `session.mcp` | MCP transport URL and headers (when using managed runtime) |
159
159
  | `session.close()` | Close session |
160
160
 
161
+ For everything the API exposes over REST beyond the session surface, see [REST client generated from the OpenAPI document](#rest-client-generated-from-the-openapi-document).
162
+
161
163
  ### Free functions
162
164
 
163
165
  `tools`, `findTools`, and `loop` are free functions that accept any `SessionBase` — they work with the managed runtime, Managed Agents sessions, and custom runtimes alike.
@@ -168,6 +170,73 @@ const result = await loop(session, {
168
170
  | `findTools(session, query)` | Search tools by name or description |
169
171
  | `loop(session, config)` | Run a Complete Loop workflow |
170
172
 
173
+ ## REST client generated from the OpenAPI document
174
+
175
+ `cs.api` reaches every operation the API publishes at
176
+ [`https://api.codespar.dev/openapi.json`](https://api.codespar.dev/openapi.json):
177
+ 215 operations across 175 paths at the snapshot this version ships. No
178
+ method is written by hand. The document is committed as
179
+ `openapi-snapshot.json`, the types under `src/generated/` are produced
180
+ from it with openapi-typescript, and the client is typed by path and
181
+ method: a path that does not declare the method does not compile, a
182
+ missing required path parameter or body field does not compile, and the
183
+ result is the documented 2xx shape.
184
+
185
+ ```typescript
186
+ import { CodeSpar } from "@codespar/sdk";
187
+
188
+ const cs = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
189
+
190
+ // 1. List wallets in the project the key is bound to.
191
+ const wallets = await cs.api.get("/v1/wallets");
192
+
193
+ // 2. Create a payment from a wallet. The gateway answers 200 (completed),
194
+ // 402 (requires approval), 403 (denied) or 422 (failed) with the same
195
+ // body shape, so read it with response() and branch on status.
196
+ const payment = await cs.api.response("post", "/v1/wallets/{id}/execute", {
197
+ path: { id: "wal_example" },
198
+ body: {
199
+ amount: 1,
200
+ currency: "BRL",
201
+ recipient: "recipient@example.com",
202
+ description: "Example payment",
203
+ mandate_id: "mnd_example",
204
+ },
205
+ });
206
+ if (payment.status === 402) {
207
+ console.log("approval needed", payment.data);
208
+ }
209
+
210
+ // 3. Read one agentic receipt by id.
211
+ const receipt = await cs.api.get("/v1/consumers/receipts/{id}", {
212
+ path: { id: "rcpt_example" },
213
+ });
214
+ console.log(receipt.state); // "paid" | "delivered" | "exception" | "voided"
215
+ ```
216
+
217
+ `get`/`post`/`put`/`patch`/`delete` and `request(method, path, options)`
218
+ return the documented 2xx data and throw `CodesparApiError` on any other
219
+ status (parsed body on `e.body`, same as the session methods).
220
+ `response(method, path, options)` returns `{ status, ok, data, response }`
221
+ for every status the document lists, discriminated on `status`. Options
222
+ carry `path`, `query`, `header` and `body` exactly as the document
223
+ declares them, plus the SDK-wide per-call `timeout` and `signal`.
224
+ Operations documented as `text/event-stream` resolve to the raw
225
+ `Response` once headers arrive.
226
+
227
+ The client only knows what the document says. A parameter a route
228
+ accepts but does not declare is not typed here; the fix is in the
229
+ document, not in this package. `createApiClient(config)` builds the same
230
+ client without a `CodeSpar` instance, and `ApiClient.operations()` lists
231
+ what it reaches.
232
+
233
+ Keeping it current: `npm run sdk:spec:refresh` (repo root) re-fetches
234
+ the document and regenerates; `npm run sdk:spec:check` fails when the
235
+ snapshot was edited by hand, when the generated files do not match the
236
+ snapshot, or when the served document no longer matches the snapshot.
237
+ The test suite pins the first two and dispatches all 215 operations
238
+ through the client.
239
+
171
240
  ## Migrating from 0.2.x
172
241
 
173
242
  `tools`, `findTools`, and `loop` moved from session instance methods to free functions in 0.3.0.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=abort.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/abort.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect, vi, afterEach } from "vitest";
2
+ import { mergeSignals, timeoutSignal } from "../internal/abort.js";
3
+ import { TimeoutError } from "../errors.js";
4
+ afterEach(() => vi.useRealTimers());
5
+ describe("mergeSignals", () => {
6
+ it("aborts when any input signal aborts, with that signal's reason", () => {
7
+ const a = new AbortController();
8
+ const b = new AbortController();
9
+ const { signal } = mergeSignals([a.signal, b.signal]);
10
+ expect(signal.aborted).toBe(false);
11
+ const reason = new Error("from-b");
12
+ b.abort(reason);
13
+ expect(signal.aborted).toBe(true);
14
+ expect(signal.reason).toBe(reason);
15
+ });
16
+ it("is already aborted if an input is already aborted", () => {
17
+ const a = new AbortController();
18
+ a.abort(new Error("pre"));
19
+ const { signal } = mergeSignals([a.signal]);
20
+ expect(signal.aborted).toBe(true);
21
+ });
22
+ it("cleanup() detaches listeners and does not abort the merged signal", () => {
23
+ const a = new AbortController();
24
+ const { signal, cleanup } = mergeSignals([a.signal]);
25
+ cleanup();
26
+ a.abort(new Error("late"));
27
+ expect(signal.aborted).toBe(false);
28
+ });
29
+ it("forwards the reason when an input is already aborted", () => {
30
+ const a = new AbortController();
31
+ const pre = new Error("pre-reason");
32
+ a.abort(pre);
33
+ const { signal } = mergeSignals([a.signal]);
34
+ expect(signal.aborted).toBe(true);
35
+ expect(signal.reason).toBe(pre);
36
+ });
37
+ it("returns a never-aborting signal for an empty or all-undefined input", () => {
38
+ const { signal: s1 } = mergeSignals([]);
39
+ const { signal: s2 } = mergeSignals([undefined]);
40
+ expect(s1.aborted).toBe(false);
41
+ expect(s2.aborted).toBe(false);
42
+ });
43
+ });
44
+ describe("timeoutSignal", () => {
45
+ it("aborts after the given ms with a TimeoutError-named reason", () => {
46
+ vi.useFakeTimers();
47
+ const { signal } = timeoutSignal(1000);
48
+ expect(signal.aborted).toBe(false);
49
+ vi.advanceTimersByTime(1000);
50
+ expect(signal.aborted).toBe(true);
51
+ expect(signal.reason.name).toBe("TimeoutError");
52
+ });
53
+ it("clear() prevents the abort", () => {
54
+ vi.useFakeTimers();
55
+ const { signal, clear } = timeoutSignal(1000);
56
+ clear();
57
+ vi.advanceTimersByTime(5000);
58
+ expect(signal.aborted).toBe(false);
59
+ });
60
+ });
61
+ describe("TimeoutError", () => {
62
+ it("is an Error subclass with name TimeoutError and a timeoutMs field", () => {
63
+ const e = new TimeoutError(1234);
64
+ expect(e).toBeInstanceOf(Error);
65
+ expect(e.name).toBe("TimeoutError");
66
+ expect(e.timeoutMs).toBe(1234);
67
+ expect(e.message).toMatch(/1234/);
68
+ });
69
+ });
70
+ //# sourceMappingURL=abort.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort.test.js","sourceRoot":"","sources":["../../src/__tests__/abort.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The generated REST client: every operation of the snapshot is
3
+ * reachable (URL, method, content types all come from the generated
4
+ * table), and the transport behaves like the rest of the SDK.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=api-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/api-client.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,286 @@
1
+ /**
2
+ * The generated REST client: every operation of the snapshot is
3
+ * reachable (URL, method, content types all come from the generated
4
+ * table), and the transport behaves like the rest of the SDK.
5
+ */
6
+ import { afterEach, describe, expect, expectTypeOf, it, vi } from "vitest";
7
+ import { ApiClient, createApiClient } from "../api/client.js";
8
+ import { API_OPERATIONS } from "../generated/operations.js";
9
+ import { CodeSpar } from "../index.js";
10
+ import { CodesparApiError, TimeoutError } from "../errors.js";
11
+ const BASE = "https://api.example.test";
12
+ const KEY = "csk_test_example";
13
+ function stubFetch(respond = () => json({})) {
14
+ const calls = [];
15
+ vi.stubGlobal("fetch", async (url, init) => {
16
+ const call = { url, init };
17
+ calls.push(call);
18
+ return respond(call);
19
+ });
20
+ return calls;
21
+ }
22
+ function json(body, status = 200) {
23
+ return new Response(JSON.stringify(body), {
24
+ status,
25
+ headers: { "content-type": "application/json; charset=utf-8" },
26
+ });
27
+ }
28
+ function client(extra = {}) {
29
+ return createApiClient({ baseUrl: BASE, apiKey: KEY, timeout: 5000, ...extra });
30
+ }
31
+ afterEach(() => {
32
+ vi.unstubAllGlobals();
33
+ });
34
+ describe("coverage: every operation in the generated table is dispatchable", () => {
35
+ it("reaches all operations of the snapshot with the documented method, URL and content types", async () => {
36
+ const calls = stubFetch((call) => call.init.headers && call.init.headers.Accept === "text/event-stream"
37
+ ? new Response("event: done\ndata: {}\n\n", {
38
+ status: 200,
39
+ headers: { "content-type": "text/event-stream" },
40
+ })
41
+ : json({ ok: true }));
42
+ const api = client();
43
+ let reached = 0;
44
+ for (const row of API_OPERATIONS) {
45
+ const names = [...row.path.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]);
46
+ const pathParams = Object.fromEntries(names.map((n) => [n, `${n}-value`]));
47
+ const expectedUrl = BASE + row.path.replace(/\{([^}]+)\}/g, (_, n) => encodeURIComponent(`${n}-value`));
48
+ const before = calls.length;
49
+ const result = (await api.response(row.method, row.path, {
50
+ path: pathParams,
51
+ body: row.body ? { example: "value" } : undefined,
52
+ }));
53
+ expect(calls.length, `${row.method} ${row.path} made one request`).toBe(before + 1);
54
+ const call = calls[before];
55
+ expect(call.url, `${row.method} ${row.path} URL`).toBe(expectedUrl);
56
+ expect(call.init.method, `${row.method} ${row.path} method`).toBe(row.method.toUpperCase());
57
+ const headers = call.init.headers;
58
+ expect(headers.Authorization).toBe(`Bearer ${KEY}`);
59
+ if (row.accept)
60
+ expect(headers.Accept, `${row.method} ${row.path} Accept`).toBe(row.accept);
61
+ else
62
+ expect(headers.Accept).toBeUndefined();
63
+ if (row.body) {
64
+ expect(headers["Content-Type"], `${row.method} ${row.path} Content-Type`).toBe(row.body);
65
+ expect(call.init.body).toBeDefined();
66
+ }
67
+ else {
68
+ expect(call.init.body).toBeUndefined();
69
+ }
70
+ expect(result.ok).toBe(true);
71
+ reached += 1;
72
+ }
73
+ expect(reached).toBe(API_OPERATIONS.length);
74
+ // The number the snapshot carries. Stated here so a snapshot refresh that
75
+ // drops routes has to change this line on purpose. 213 at #139; 215 after
76
+ // the 2026-09-10 refresh (`/v1/fees`, `/v1/fees/movimentar`).
77
+ expect(API_OPERATIONS.length).toBe(215);
78
+ });
79
+ it("refuses a method/path pair the document does not declare, before any request", async () => {
80
+ const calls = stubFetch();
81
+ const api = client();
82
+ await expect(api.request("get", "/v1/not-in-the-document")).rejects.toThrow(/not an operation of the OpenAPI document/);
83
+ await expect(api.request("put", "/v1/wallets")).rejects.toThrow(/PUT \/v1\/wallets is not/);
84
+ expect(calls).toHaveLength(0);
85
+ });
86
+ });
87
+ describe("request shaping", () => {
88
+ it("encodes path parameters and refuses a missing one before fetching", async () => {
89
+ const calls = stubFetch();
90
+ const api = client();
91
+ await api.get("/v1/wallets/{id}", { path: { id: "wal_a/b c" } });
92
+ expect(calls[0].url).toBe(`${BASE}/v1/wallets/wal_a%2Fb%20c`);
93
+ await expect(api.request("get", "/v1/wallets/{id}", { path: {} })).rejects.toThrow(/missing path parameter id/);
94
+ expect(calls).toHaveLength(1);
95
+ });
96
+ it("serialises query parameters, repeating arrays and skipping undefined", async () => {
97
+ const calls = stubFetch();
98
+ const api = client();
99
+ await api.request("get", "/v1/wallets", {
100
+ query: { limit: 10, status: ["a", "b"], cursor: undefined, flag: false },
101
+ });
102
+ const url = new URL(calls[0].url);
103
+ expect(url.pathname).toBe("/v1/wallets");
104
+ expect(url.searchParams.getAll("status")).toEqual(["a", "b"]);
105
+ expect(url.searchParams.get("limit")).toBe("10");
106
+ expect(url.searchParams.get("flag")).toBe("false");
107
+ expect(url.searchParams.has("cursor")).toBe(false);
108
+ });
109
+ it("sends JSON bodies with the documented content type", async () => {
110
+ const calls = stubFetch(() => json({ id: "wal_example" }, 201));
111
+ const api = client();
112
+ const wallet = await api.post("/v1/wallets", {
113
+ body: { display_name: "Example wallet", currency: "BRL" },
114
+ });
115
+ expect(wallet).toEqual({ id: "wal_example" });
116
+ expect(calls[0].init.body).toBe(JSON.stringify({ display_name: "Example wallet", currency: "BRL" }));
117
+ expect(calls[0].init.headers["Content-Type"]).toBe("application/json");
118
+ });
119
+ it("sends form bodies for x-www-form-urlencoded operations", async () => {
120
+ const calls = stubFetch();
121
+ const api = client();
122
+ await api.post("/oauth/token", {
123
+ body: { grant_type: "authorization_code", code: "code-value" },
124
+ });
125
+ const headers = calls[0].init.headers;
126
+ expect(headers["Content-Type"]).toBe("application/x-www-form-urlencoded");
127
+ expect(String(calls[0].init.body)).toBe("grant_type=authorization_code&code=code-value");
128
+ });
129
+ it("carries the project scope and per-call header parameters", async () => {
130
+ const calls = stubFetch();
131
+ const api = client({ projectId: "prj_abc123DEF456ghi7" });
132
+ await api.patch("/v1/audit-events/config", {
133
+ header: { "x-codespar-user": "user_example" },
134
+ body: {},
135
+ });
136
+ const headers = calls[0].init.headers;
137
+ expect(headers["x-codespar-project"]).toBe("prj_abc123DEF456ghi7");
138
+ expect(headers["x-codespar-user"]).toBe("user_example");
139
+ });
140
+ it("tolerates a trailing slash on baseUrl", async () => {
141
+ const calls = stubFetch();
142
+ await client({ baseUrl: `${BASE}/` }).get("/v1/health");
143
+ expect(calls[0].url).toBe(`${BASE}/v1/health`);
144
+ });
145
+ });
146
+ describe("responses and errors", () => {
147
+ it("request() throws CodesparApiError with the parsed body on a non-2xx", async () => {
148
+ stubFetch(() => json({ error: "not_found" }, 404));
149
+ const api = client();
150
+ const err = await api.get("/v1/wallets/{id}", { path: { id: "wal_missing" } }).catch((e) => e);
151
+ expect(err).toBeInstanceOf(CodesparApiError);
152
+ expect(err.status).toBe(404);
153
+ expect(err.code).toBe("not_found");
154
+ expect(err.body).toEqual({ error: "not_found" });
155
+ expect(err.message).toMatch(/^GET \/v1\/wallets\/\{id\} failed: 404/);
156
+ });
157
+ it("response() returns non-2xx statuses as values, discriminated on status", async () => {
158
+ stubFetch(() => json({ status: "requires-approval" }, 402));
159
+ const api = client();
160
+ const r = await api.response("post", "/v1/wallets/{id}/execute", {
161
+ path: { id: "wal_example" },
162
+ body: {
163
+ amount: 1,
164
+ currency: "BRL",
165
+ recipient: "recipient-example",
166
+ description: "example",
167
+ mandate_id: "mnd_example",
168
+ },
169
+ });
170
+ expect(r.status).toBe(402);
171
+ expect(r.ok).toBe(false);
172
+ expect(r.data).toEqual({ status: "requires-approval" });
173
+ expect(r.response.status).toBe(402);
174
+ });
175
+ it("returns undefined for an empty body and text for a non-JSON one", async () => {
176
+ stubFetch((call) => call.url.endsWith("/v1/health")
177
+ ? new Response(null, { status: 204 })
178
+ : new Response("<html></html>", { status: 200, headers: { "content-type": "text/html" } }));
179
+ const api = client();
180
+ expect(await api.get("/v1/health")).toBeUndefined();
181
+ expect(await api.get("/oauth/authorize", { query: {} })).toBe("<html></html>");
182
+ });
183
+ it("returns the raw Response for text/event-stream operations", async () => {
184
+ stubFetch(() => new Response("event: snapshot\ndata: {}\n\n", {
185
+ status: 200,
186
+ headers: { "content-type": "text/event-stream" },
187
+ }));
188
+ const api = client();
189
+ const res = await api.get("/v1/tool-calls/{id}/payment-status/stream", {
190
+ path: { id: "tc_example" },
191
+ });
192
+ expect(res).toBeInstanceOf(Response);
193
+ expect(await res.text()).toContain("event: snapshot");
194
+ });
195
+ it("maps a fetch rejection to CodesparApiError status 0 with the cause attached", async () => {
196
+ const boom = new TypeError("fetch failed");
197
+ vi.stubGlobal("fetch", async () => {
198
+ throw boom;
199
+ });
200
+ const err = await client().get("/v1/health").catch((e) => e);
201
+ expect(err).toBeInstanceOf(CodesparApiError);
202
+ expect(err.status).toBe(0);
203
+ expect(err.cause).toBe(boom);
204
+ });
205
+ it("times out with TimeoutError when the backend never answers", async () => {
206
+ vi.stubGlobal("fetch", (_url, init) => new Promise((_, reject) => init.signal?.addEventListener("abort", () => reject(init.signal.reason))));
207
+ const err = await client().get("/v1/health", { timeout: 20 }).catch((e) => e);
208
+ expect(err).toBeInstanceOf(TimeoutError);
209
+ expect(err.timeoutMs).toBe(20);
210
+ });
211
+ it("propagates the caller's abort reason verbatim", async () => {
212
+ vi.stubGlobal("fetch", (_url, init) => new Promise((_, reject) => init.signal?.addEventListener("abort", () => reject(init.signal.reason))));
213
+ const ac = new AbortController();
214
+ const reason = new Error("caller cancelled");
215
+ const pending = client().get("/v1/health", { signal: ac.signal });
216
+ ac.abort(reason);
217
+ await expect(pending).rejects.toBe(reason);
218
+ });
219
+ it("rejects an invalid per-call timeout before fetching", async () => {
220
+ const calls = stubFetch();
221
+ await expect(client().get("/v1/health", { timeout: 0 })).rejects.toThrow(/timeout must be/);
222
+ expect(calls).toHaveLength(0);
223
+ });
224
+ });
225
+ describe("CodeSpar.api", () => {
226
+ it("shares the client's credentials, base URL, project and timeout", async () => {
227
+ const calls = stubFetch();
228
+ const cs = new CodeSpar({
229
+ apiKey: KEY,
230
+ baseUrl: BASE,
231
+ projectId: "prj_abc123DEF456ghi7",
232
+ timeout: 1234,
233
+ });
234
+ expect(cs.api).toBeInstanceOf(ApiClient);
235
+ await cs.api.get("/v1/whoami");
236
+ const headers = calls[0].init.headers;
237
+ expect(calls[0].url).toBe(`${BASE}/v1/whoami`);
238
+ expect(headers.Authorization).toBe(`Bearer ${KEY}`);
239
+ expect(headers["x-codespar-project"]).toBe("prj_abc123DEF456ghi7");
240
+ });
241
+ });
242
+ describe("README examples (the three snippets, compiled and dispatched)", () => {
243
+ it("list wallets, create a payment, read a receipt", async () => {
244
+ const calls = stubFetch((call) => call.url.endsWith("/execute")
245
+ ? json({ status: "requires-approval" }, 402)
246
+ : call.url.includes("/receipts/")
247
+ ? json({ receipt_id: "rcpt_example", state: "paid" })
248
+ : json([]));
249
+ const cs = new CodeSpar({ apiKey: KEY, baseUrl: BASE });
250
+ const wallets = await cs.api.get("/v1/wallets");
251
+ expect(wallets).toEqual([]);
252
+ const payment = await cs.api.response("post", "/v1/wallets/{id}/execute", {
253
+ path: { id: "wal_example" },
254
+ body: {
255
+ amount: 1,
256
+ currency: "BRL",
257
+ recipient: "recipient@example.com",
258
+ description: "Example payment",
259
+ mandate_id: "mnd_example",
260
+ },
261
+ });
262
+ expect(payment.status).toBe(402);
263
+ if (payment.status === 402)
264
+ expect(payment.data.status).toBe("requires-approval");
265
+ const receipt = await cs.api.get("/v1/consumers/receipts/{id}", {
266
+ path: { id: "rcpt_example" },
267
+ });
268
+ expect(receipt.state).toBe("paid");
269
+ expect(calls.map((c) => `${c.init.method} ${new URL(c.url).pathname}`)).toEqual([
270
+ "GET /v1/wallets",
271
+ "POST /v1/wallets/wal_example/execute",
272
+ "GET /v1/consumers/receipts/rcpt_example",
273
+ ]);
274
+ });
275
+ });
276
+ describe("types (checked by tsc, not at runtime)", () => {
277
+ it("path parameters are required where the document declares them", () => {
278
+ expectTypeOf().toEqualTypeOf();
279
+ expectTypeOf().toHaveProperty("id");
280
+ expectTypeOf().toMatchTypeOf();
281
+ // A path that does not declare the method is not an accepted argument.
282
+ expectTypeOf().toMatchTypeOf();
283
+ expectTypeOf().not.toMatchTypeOf();
284
+ });
285
+ });
286
+ //# sourceMappingURL=api-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.test.js","sourceRoot":"","sources":["../../src/__tests__/api-client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=close-timeout.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-timeout.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/close-timeout.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
1
+ import { describe, it, expect, afterEach } from "vitest";
2
+ import { CodeSpar } from "../index.js";
3
+ const realFetch = globalThis.fetch;
4
+ afterEach(() => { globalThis.fetch = realFetch; });
5
+ function sessionCreate() {
6
+ return { ok: true, status: 201, text: async () => "", json: async () => ({
7
+ id: "ses_c", org_id: "o", user_id: "u", servers: [],
8
+ status: "active", created_at: new Date().toISOString(), closed_at: null,
9
+ }) };
10
+ }
11
+ describe("session.close timeout", () => {
12
+ it("close() is best-effort: a DELETE timeout is swallowed, not thrown", async () => {
13
+ // Backend accepts the DELETE socket but never responds. close()
14
+ // must stay bounded (the timeout budget still fires) AND best-effort
15
+ // (it does not surface the timeout to the caller — parity with the
16
+ // Python client and the managed-agents adapter).
17
+ globalThis.fetch = ((url, init) => {
18
+ if (String(url).endsWith("/v1/sessions"))
19
+ return Promise.resolve(sessionCreate());
20
+ return new Promise((_res, rej) => {
21
+ init?.signal?.addEventListener("abort", () => rej(init.signal.reason), { once: true });
22
+ });
23
+ });
24
+ const cs = new CodeSpar({ apiKey: "csk_live_t", baseUrl: "https://x", timeout: 50 });
25
+ const session = await cs.create("u");
26
+ const start = Date.now();
27
+ await expect(session.close()).resolves.toBeUndefined();
28
+ // Bounded: it returned because the 50ms budget fired, not because
29
+ // it hung until the 5s test timeout.
30
+ expect(Date.now() - start).toBeLessThan(2000);
31
+ }, 5000);
32
+ it("close() still validates the timeout (invalid value is NOT swallowed)", async () => {
33
+ globalThis.fetch = ((url) => {
34
+ if (String(url).endsWith("/v1/sessions"))
35
+ return Promise.resolve(sessionCreate());
36
+ return Promise.resolve({ ok: true, status: 204, text: async () => "" });
37
+ });
38
+ const cs = new CodeSpar({ apiKey: "csk_live_t", baseUrl: "https://x" });
39
+ const session = await cs.create("u");
40
+ await expect(session.close({ timeout: 0 })).rejects.toThrow(/timeout/i);
41
+ }, 5000);
42
+ it("close() stays best-effort with a per-call timeout override", async () => {
43
+ globalThis.fetch = ((url, init) => {
44
+ if (String(url).endsWith("/v1/sessions"))
45
+ return Promise.resolve(sessionCreate());
46
+ return new Promise((_res, rej) => {
47
+ init?.signal?.addEventListener("abort", () => rej(init.signal.reason), { once: true });
48
+ });
49
+ });
50
+ const cs = new CodeSpar({ apiKey: "csk_live_t", baseUrl: "https://x", timeout: 10_000 });
51
+ const session = await cs.create("u");
52
+ const start = Date.now();
53
+ await expect(session.close({ timeout: 50 })).resolves.toBeUndefined();
54
+ expect(Date.now() - start).toBeLessThan(2000);
55
+ }, 5000);
56
+ });
57
+ //# sourceMappingURL=close-timeout.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-timeout.test.js","sourceRoot":"","sources":["../../src/__tests__/close-timeout.test.ts"],"names":[],"mappings":"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"}
@@ -66,6 +66,17 @@ describe("CodeSpar constructor", () => {
66
66
  delete process.env.CODESPAR_BASE_URL;
67
67
  }
68
68
  });
69
+ it("defaults timeout to 60000 and accepts an override", () => {
70
+ const a = new CodeSpar({ apiKey: "csk_live_t" });
71
+ // @ts-expect-error private config read for the test only
72
+ expect(a.config.timeout).toBe(60000);
73
+ const b = new CodeSpar({ apiKey: "csk_live_t", timeout: 5000 });
74
+ // @ts-expect-error private config read for the test only
75
+ expect(b.config.timeout).toBe(5000);
76
+ });
77
+ it.each([0, -1, NaN, Infinity])("rejects an invalid default timeout (%p) at construction", (bad) => {
78
+ expect(() => new CodeSpar({ apiKey: "csk_live_t", timeout: bad })).toThrow(/timeout/i);
79
+ });
69
80
  });
70
81
  describe("SessionConfigSchema", () => {
71
82
  it("accepts an empty config", () => {