@aithos/sdk 0.1.0-alpha.39 → 0.1.0-alpha.40

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 (45) hide show
  1. package/dist/src/assets.d.ts +207 -0
  2. package/dist/src/assets.js +533 -0
  3. package/dist/src/index.d.ts +1 -0
  4. package/dist/src/index.js +6 -0
  5. package/dist/src/react/AithosAsset.d.ts +66 -0
  6. package/dist/src/react/AithosAsset.js +67 -0
  7. package/dist/src/react/context.d.ts +29 -0
  8. package/dist/src/react/context.js +31 -0
  9. package/dist/src/react/index.d.ts +28 -0
  10. package/dist/src/react/index.js +30 -0
  11. package/dist/src/react/use-aithos-asset.d.ts +39 -0
  12. package/dist/src/react/use-aithos-asset.js +118 -0
  13. package/package.json +16 -2
  14. package/dist/test/auth-j3.test.d.ts +0 -2
  15. package/dist/test/auth-j3.test.js +0 -391
  16. package/dist/test/auth.test.d.ts +0 -2
  17. package/dist/test/auth.test.js +0 -175
  18. package/dist/test/compute-delegate-path.test.d.ts +0 -2
  19. package/dist/test/compute-delegate-path.test.js +0 -183
  20. package/dist/test/compute.test.d.ts +0 -2
  21. package/dist/test/compute.test.js +0 -194
  22. package/dist/test/endpoints.test.d.ts +0 -2
  23. package/dist/test/endpoints.test.js +0 -62
  24. package/dist/test/envelope.test.d.ts +0 -2
  25. package/dist/test/envelope.test.js +0 -318
  26. package/dist/test/ethos-first-edition.test.d.ts +0 -2
  27. package/dist/test/ethos-first-edition.test.js +0 -248
  28. package/dist/test/ethos.test.d.ts +0 -2
  29. package/dist/test/ethos.test.js +0 -219
  30. package/dist/test/key-store.test.d.ts +0 -2
  31. package/dist/test/key-store.test.js +0 -161
  32. package/dist/test/mandates-compute.test.d.ts +0 -2
  33. package/dist/test/mandates-compute.test.js +0 -256
  34. package/dist/test/mandates.test.d.ts +0 -2
  35. package/dist/test/mandates.test.js +0 -93
  36. package/dist/test/sdk.test.d.ts +0 -2
  37. package/dist/test/sdk.test.js +0 -126
  38. package/dist/test/signer.test.d.ts +0 -2
  39. package/dist/test/signer.test.js +0 -117
  40. package/dist/test/signup-bootstrap.test.d.ts +0 -2
  41. package/dist/test/signup-bootstrap.test.js +0 -311
  42. package/dist/test/wallet.test.d.ts +0 -2
  43. package/dist/test/wallet.test.js +0 -121
  44. package/dist/test/web.test.d.ts +0 -2
  45. package/dist/test/web.test.js +0 -270
@@ -1,121 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // Copyright 2026 Mathieu Colla
3
- // Unit tests for sdk.wallet.createTopupSession with a mock fetch.
4
- import { strict as assert } from "node:assert";
5
- import { describe, it } from "node:test";
6
- import { createBrowserIdentity } from "@aithos/protocol-client";
7
- import { AithosAuth, AithosSDK, AithosSDKError, memoryKeyStore, noopStore, } from "../src/index.js";
8
- import { serializeRecoveryFile } from "../src/internal/recovery-file.js";
9
- const APP_DID = "did:aithos:app:test";
10
- async function makeSdk(fetchImpl) {
11
- const id = createBrowserIdentity("test-handle", "Test User");
12
- const auth = new AithosAuth({
13
- authBaseUrl: "https://auth.test",
14
- fetch: (() => {
15
- throw new Error("auth not used in wallet tests");
16
- }),
17
- sessionStore: noopStore(),
18
- keyStore: memoryKeyStore(),
19
- });
20
- const { text } = serializeRecoveryFile(id);
21
- await auth.signInWithRecovery({ file: text });
22
- return new AithosSDK({
23
- auth,
24
- appDid: APP_DID,
25
- endpoints: { wallet: "https://wallet.example.test" },
26
- fetch: fetchImpl,
27
- });
28
- }
29
- describe("wallet.createTopupSession — happy path", () => {
30
- it("posts user_did + pack_id + urls and returns the hosted URL", async () => {
31
- let capturedUrl;
32
- let capturedBody;
33
- const fakeFetch = async (input, init) => {
34
- capturedUrl = typeof input === "string" ? input : input.toString();
35
- capturedBody = JSON.parse(init?.body);
36
- return new Response(JSON.stringify({
37
- checkout_url: "https://checkout.stripe.com/c/pay/cs_test_xyz",
38
- session_id: "cs_test_xyz",
39
- }), { status: 200, headers: { "content-type": "application/json" } });
40
- };
41
- const sdk = await makeSdk(fakeFetch);
42
- const out = await sdk.wallet.createTopupSession({
43
- packId: "credits-1m",
44
- successUrl: "https://app.example.com/?topup=success",
45
- cancelUrl: "https://app.example.com/?topup=cancel",
46
- });
47
- assert.equal(out.checkoutUrl, "https://checkout.stripe.com/c/pay/cs_test_xyz");
48
- assert.equal(out.sessionId, "cs_test_xyz");
49
- assert.equal(capturedUrl, "https://wallet.example.test/v1/wallet/topup/checkout");
50
- assert.equal(capturedBody?.user_did, sdk.userDid);
51
- assert.equal(capturedBody?.pack_id, "credits-1m");
52
- assert.equal(capturedBody?.success_url, "https://app.example.com/?topup=success");
53
- assert.equal(capturedBody?.cancel_url, "https://app.example.com/?topup=cancel");
54
- });
55
- });
56
- describe("wallet.createTopupSession — errors", () => {
57
- it("wraps a network failure as AithosSDKError(code='network')", async () => {
58
- const fakeFetch = async () => {
59
- throw new TypeError("Failed to fetch");
60
- };
61
- const sdk = await makeSdk(fakeFetch);
62
- await assert.rejects(sdk.wallet.createTopupSession({
63
- packId: "credits-100k",
64
- successUrl: "https://app.example.com/?ok",
65
- cancelUrl: "https://app.example.com/?ko",
66
- }), (err) => {
67
- assert.ok(err instanceof AithosSDKError);
68
- assert.equal(err.code, "network");
69
- return true;
70
- });
71
- });
72
- it("surfaces the proxy's structured error (error/detail) on a 4xx", async () => {
73
- const fakeFetch = async () => new Response(JSON.stringify({ error: "unknown_pack", pack_id: "credits-9999" }), { status: 400, headers: { "content-type": "application/json" } });
74
- const sdk = await makeSdk(fakeFetch);
75
- await assert.rejects(sdk.wallet.createTopupSession({
76
- // @ts-expect-error: deliberately invalid pack id
77
- packId: "credits-9999",
78
- successUrl: "https://app.example.com/?ok",
79
- cancelUrl: "https://app.example.com/?ko",
80
- }), (err) => {
81
- assert.ok(err instanceof AithosSDKError);
82
- assert.equal(err.code, "unknown_pack");
83
- assert.equal(err.status, 400);
84
- return true;
85
- });
86
- });
87
- it("rejects a non-JSON response as AithosSDKError(code='http')", async () => {
88
- const fakeFetch = async () => new Response("<html>500</html>", {
89
- status: 500,
90
- headers: { "content-type": "text/html" },
91
- });
92
- const sdk = await makeSdk(fakeFetch);
93
- await assert.rejects(sdk.wallet.createTopupSession({
94
- packId: "credits-100k",
95
- successUrl: "https://app.example.com/?ok",
96
- cancelUrl: "https://app.example.com/?ko",
97
- }), (err) => {
98
- assert.ok(err instanceof AithosSDKError);
99
- assert.equal(err.code, "http");
100
- assert.equal(err.status, 500);
101
- return true;
102
- });
103
- });
104
- it("rejects a 200 with missing fields as AithosSDKError(code='empty')", async () => {
105
- const fakeFetch = async () => new Response(JSON.stringify({}), {
106
- status: 200,
107
- headers: { "content-type": "application/json" },
108
- });
109
- const sdk = await makeSdk(fakeFetch);
110
- await assert.rejects(sdk.wallet.createTopupSession({
111
- packId: "credits-100k",
112
- successUrl: "https://app.example.com/?ok",
113
- cancelUrl: "https://app.example.com/?ko",
114
- }), (err) => {
115
- assert.ok(err instanceof AithosSDKError);
116
- assert.equal(err.code, "empty");
117
- return true;
118
- });
119
- });
120
- });
121
- //# sourceMappingURL=wallet.test.js.map
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=web.test.d.ts.map
@@ -1,270 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // Copyright 2026 Mathieu Colla
3
- // Unit tests for sdk.web.extract with a mock fetch.
4
- //
5
- // Mirrors test/compute.test.ts: real BrowserIdentity (synchronous Ed25519)
6
- // so the envelope-signing path runs for real and any
7
- // signature/canonicalization regression surfaces here.
8
- import { strict as assert } from "node:assert";
9
- import { describe, it } from "node:test";
10
- import { createBrowserIdentity } from "@aithos/protocol-client";
11
- import { AithosAuth, AithosSDK, AithosSDKError, memoryKeyStore, noopStore, } from "../src/index.js";
12
- import { serializeRecoveryFile } from "../src/internal/recovery-file.js";
13
- const APP_DID = "did:aithos:app:test";
14
- async function makeSdk(fetchImpl) {
15
- const id = createBrowserIdentity("test-handle", "Test User");
16
- const auth = new AithosAuth({
17
- authBaseUrl: "https://auth.test",
18
- fetch: (() => {
19
- throw new Error("auth not used in web tests");
20
- }),
21
- sessionStore: noopStore(),
22
- keyStore: memoryKeyStore(),
23
- });
24
- const { text } = serializeRecoveryFile(id);
25
- await auth.signInWithRecovery({ file: text });
26
- return new AithosSDK({
27
- auth,
28
- appDid: APP_DID,
29
- endpoints: { web: "https://extract.example.test" },
30
- fetch: fetchImpl,
31
- });
32
- }
33
- const HAPPY_RESULT = {
34
- data: {
35
- url: "https://example.com",
36
- final_url: "https://example.com/",
37
- fetched_at: "2026-05-13T05:30:00.000Z",
38
- render_ms: 1234,
39
- meta: {
40
- title: "Example",
41
- description: null,
42
- lang: "en",
43
- charset: "UTF-8",
44
- viewport: null,
45
- canonical: null,
46
- og: {},
47
- },
48
- structure: { headings: [], sections: [], nav_links: [], forms: [] },
49
- content: {
50
- main_html: "<main>hi</main>",
51
- main_text: "hi",
52
- images: [],
53
- links: { internal: [], external: [] },
54
- },
55
- styles: { css: "", inline_styles_count: 0 },
56
- visual_signature: {
57
- colors: {
58
- palette: [],
59
- background: "#ffffff",
60
- text: "#000000",
61
- primary: null,
62
- link: null,
63
- },
64
- typography: {
65
- heading_font: null,
66
- body_font: "sans-serif",
67
- size_scale: [],
68
- base_size_px: 16,
69
- base_line_height: 1.5,
70
- },
71
- radii: { button: null, input: null, card: null },
72
- spacing: { base_unit_px: null, common_gaps_px: [] },
73
- layout: { max_content_width_px: null, mode: "block" },
74
- components: { buttons: [], inputs: [], cards: [] },
75
- },
76
- logo: null,
77
- },
78
- creditsCharged: 1,
79
- walletBalance: 99_999,
80
- auditId: "audit-web-1",
81
- };
82
- describe("web.extract — happy path", () => {
83
- it("posts to ${web}/v1/invoke with a JSON-RPC envelope and parses the result", async () => {
84
- let capturedUrl;
85
- let capturedInit;
86
- const fakeFetch = async (input, init) => {
87
- capturedUrl = typeof input === "string" ? input : input.toString();
88
- capturedInit = init;
89
- return new Response(JSON.stringify({ result: HAPPY_RESULT }), {
90
- status: 200,
91
- headers: { "content-type": "application/json" },
92
- });
93
- };
94
- const sdk = await makeSdk(fakeFetch);
95
- const out = await sdk.web.extract({ url: "https://example.com" });
96
- assert.deepEqual(out, HAPPY_RESULT);
97
- assert.equal(capturedUrl, "https://extract.example.test/v1/invoke");
98
- assert.equal(capturedInit?.method, "POST");
99
- const headers = capturedInit?.headers;
100
- assert.equal(headers["content-type"], "application/json");
101
- const body = JSON.parse(capturedInit?.body);
102
- assert.equal(body.jsonrpc, "2.0");
103
- assert.equal(body.method, "aithos.web_extract");
104
- assert.equal(body.params.url, "https://example.com");
105
- assert.equal(body.params.app_did, APP_DID);
106
- assert.ok(typeof body.params.mandate_id === "string");
107
- assert.ok(body.params.mandate_id.length > 0);
108
- assert.ok(body.params._envelope, "request must carry a signed envelope");
109
- });
110
- it("forwards waitUntil and timeoutMs as snake_case-free params", async () => {
111
- let capturedBody;
112
- const fakeFetch = async (_input, init) => {
113
- capturedBody = JSON.parse(init.body);
114
- return new Response(JSON.stringify({ result: HAPPY_RESULT }), {
115
- status: 200,
116
- headers: { "content-type": "application/json" },
117
- });
118
- };
119
- const sdk = await makeSdk(fakeFetch);
120
- await sdk.web.extract({
121
- url: "https://example.com",
122
- waitUntil: "domcontentloaded",
123
- timeoutMs: 5000,
124
- });
125
- assert.equal(capturedBody?.params.waitUntil, "domcontentloaded");
126
- assert.equal(capturedBody?.params.timeoutMs, 5000);
127
- });
128
- });
129
- describe("web.extract — error mapping", () => {
130
- it("propagates -32071 insufficient_balance as AithosSDKError with data", async () => {
131
- const fakeFetch = async () => new Response(JSON.stringify({
132
- error: {
133
- code: -32071,
134
- message: "Insufficient balance",
135
- data: { required: 1, available: 0 },
136
- },
137
- }), { status: 200, headers: { "content-type": "application/json" } });
138
- const sdk = await makeSdk(fakeFetch);
139
- await assert.rejects(() => sdk.web.extract({ url: "https://example.com" }), (err) => {
140
- assert.ok(err instanceof AithosSDKError);
141
- assert.equal(err.code, "-32071");
142
- const data = err.data;
143
- assert.equal(data?.required, 1);
144
- assert.equal(data?.available, 0);
145
- return true;
146
- });
147
- });
148
- it("propagates -32042 scope mismatch as AithosSDKError", async () => {
149
- const fakeFetch = async () => new Response(JSON.stringify({
150
- error: {
151
- code: -32042,
152
- message: "mandate does not carry the web.extract scope",
153
- data: {
154
- mandate_id: "mandate:abc",
155
- required_scope: "web.extract",
156
- },
157
- },
158
- }), { status: 200, headers: { "content-type": "application/json" } });
159
- const sdk = await makeSdk(fakeFetch);
160
- await assert.rejects(() => sdk.web.extract({ url: "https://example.com" }), (err) => {
161
- assert.ok(err instanceof AithosSDKError);
162
- assert.equal(err.code, "-32042");
163
- return true;
164
- });
165
- });
166
- it("rejects HTTP transport errors as AithosSDKError code=http", async () => {
167
- const fakeFetch = async () => new Response("upstream is down", { status: 502 });
168
- const sdk = await makeSdk(fakeFetch);
169
- await assert.rejects(() => sdk.web.extract({ url: "https://example.com" }), (err) => {
170
- assert.ok(err instanceof AithosSDKError);
171
- assert.equal(err.code, "http");
172
- return true;
173
- });
174
- });
175
- });
176
- describe("web.extract — endpoint default", () => {
177
- it("defaults to https://extract.aithos.be when no override is given", async () => {
178
- let capturedUrl;
179
- const fakeFetch = async (input) => {
180
- capturedUrl = typeof input === "string" ? input : input.toString();
181
- return new Response(JSON.stringify({ result: HAPPY_RESULT }), {
182
- status: 200,
183
- headers: { "content-type": "application/json" },
184
- });
185
- };
186
- const id = createBrowserIdentity("test-handle", "Test User");
187
- const auth = new AithosAuth({
188
- authBaseUrl: "https://auth.test",
189
- fetch: (() => {
190
- throw new Error("auth not used");
191
- }),
192
- sessionStore: noopStore(),
193
- keyStore: memoryKeyStore(),
194
- });
195
- const { text } = serializeRecoveryFile(id);
196
- await auth.signInWithRecovery({ file: text });
197
- const sdk = new AithosSDK({
198
- auth,
199
- appDid: APP_DID,
200
- fetch: fakeFetch,
201
- });
202
- await sdk.web.extract({ url: "https://example.com" });
203
- assert.equal(capturedUrl, "https://extract.aithos.be/v1/invoke");
204
- });
205
- });
206
- describe("web.fetchAsset — happy path", () => {
207
- it("posts to ${web}/v1/invoke with method aithos.web_fetch_asset", async () => {
208
- let capturedUrl;
209
- let capturedInit;
210
- const fakeResult = {
211
- data: {
212
- url: "https://example.com/logo.png",
213
- final_url: "https://example.com/logo.png",
214
- content_type: "image/png",
215
- size_bytes: 4096,
216
- base64: "aGVsbG8K",
217
- },
218
- creditsCharged: 1,
219
- walletBalance: 99_998,
220
- auditId: "audit-asset-1",
221
- };
222
- const fakeFetch = async (input, init) => {
223
- capturedUrl = typeof input === "string" ? input : input.toString();
224
- capturedInit = init;
225
- return new Response(JSON.stringify({ result: fakeResult }), {
226
- status: 200,
227
- headers: { "content-type": "application/json" },
228
- });
229
- };
230
- const sdk = await makeSdk(fakeFetch);
231
- const out = await sdk.web.fetchAsset({ url: "https://example.com/logo.png" });
232
- assert.deepEqual(out, fakeResult);
233
- assert.equal(capturedUrl, "https://extract.example.test/v1/invoke");
234
- const body = JSON.parse(capturedInit?.body);
235
- assert.equal(body.method, "aithos.web_fetch_asset");
236
- assert.equal(body.params.url, "https://example.com/logo.png");
237
- assert.equal(body.params.app_did, APP_DID);
238
- assert.ok(typeof body.params.mandate_id === "string");
239
- assert.ok(body.params._envelope, "request must carry a signed envelope");
240
- });
241
- });
242
- describe("web.fetchAsset — error propagation", () => {
243
- it("propagates -32071 insufficient_balance as AithosSDKError", async () => {
244
- const fakeFetch = async () => new Response(JSON.stringify({
245
- error: {
246
- code: -32071,
247
- message: "Insufficient balance",
248
- data: { required: 1, available: 0 },
249
- },
250
- }), { status: 200, headers: { "content-type": "application/json" } });
251
- const sdk = await makeSdk(fakeFetch);
252
- await assert.rejects(() => sdk.web.fetchAsset({ url: "https://example.com/logo.png" }), (err) => {
253
- assert.ok(err instanceof AithosSDKError);
254
- assert.equal(err.code, "-32071");
255
- return true;
256
- });
257
- });
258
- it("propagates -32000 upstream fetch failure as AithosSDKError", async () => {
259
- const fakeFetch = async () => new Response(JSON.stringify({
260
- error: { code: -32000, message: "Asset fetch failed", data: { reason: "upstream HTTP 404" } },
261
- }), { status: 200, headers: { "content-type": "application/json" } });
262
- const sdk = await makeSdk(fakeFetch);
263
- await assert.rejects(() => sdk.web.fetchAsset({ url: "https://example.com/missing.png" }), (err) => {
264
- assert.ok(err instanceof AithosSDKError);
265
- assert.equal(err.code, "-32000");
266
- return true;
267
- });
268
- });
269
- });
270
- //# sourceMappingURL=web.test.js.map