@unbrowse/sdk 6.17.0-preview.6
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/LICENSE +21 -0
- package/README.md +156 -0
- package/dist/client.d.ts +120 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +379 -0
- package/dist/client.js.map +1 -0
- package/dist/contracts.d.ts +372 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +2 -0
- package/dist/contracts.js.map +1 -0
- package/dist/errors.d.ts +45 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +72 -0
- package/dist/errors.js.map +1 -0
- package/dist/flex.d.ts +178 -0
- package/dist/flex.d.ts.map +1 -0
- package/dist/flex.js +299 -0
- package/dist/flex.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +70 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +326 -0
- package/dist/runtime.js.map +1 -0
- package/dist/x402.d.ts +75 -0
- package/dist/x402.d.ts.map +1 -0
- package/dist/x402.js +29 -0
- package/dist/x402.js.map +1 -0
- package/package.json +46 -0
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-binary lifecycle for `@unbrowse/sdk`.
|
|
3
|
+
*
|
|
4
|
+
* The SDK talks to a co-located `unbrowse` runtime over loopback HTTP.
|
|
5
|
+
* `runtime.ts` owns the contract for locating, probing, and spawning that
|
|
6
|
+
* runtime so `client.ts` can stay a pure HTTP transport.
|
|
7
|
+
*
|
|
8
|
+
* Tree-shaking note: heavy Node-only imports (`child_process`) are pulled
|
|
9
|
+
* in lazily inside `spawnUnbrowseRuntime`. Callers that only use
|
|
10
|
+
* `Unbrowse.connect` never pay for them.
|
|
11
|
+
*/
|
|
12
|
+
import { RuntimeUnavailableError } from "./errors.js";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
// Under Node ESM (`"type": "module"` + tsc `module: ESNext`), bare `require`
|
|
15
|
+
// is undefined and the lazy `require("node:fs")` / `require("node:path")`
|
|
16
|
+
// calls below would throw `ReferenceError`, get swallowed by their try/catch,
|
|
17
|
+
// and silently return false/null. Bind a CommonJS-style require to this
|
|
18
|
+
// module's URL so all the lazy `require(...)` sites in this file resolve.
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
|
+
const require = createRequire(import.meta.url);
|
|
21
|
+
const DEFAULT_PORT = 6969;
|
|
22
|
+
const DEFAULT_READY_TIMEOUT_MS = 10_000;
|
|
23
|
+
const DEFAULT_PROBE_TIMEOUT_MS = 1_000;
|
|
24
|
+
/**
|
|
25
|
+
* Probe an already-running runtime by hitting `/health`. Returns true iff
|
|
26
|
+
* the response status is 2xx. Never throws — connection refused, timeout,
|
|
27
|
+
* DNS failures, and non-2xx all resolve to `false`.
|
|
28
|
+
*/
|
|
29
|
+
export async function probeUnbrowseRuntime(baseUrl, timeoutMs = DEFAULT_PROBE_TIMEOUT_MS) {
|
|
30
|
+
const url = `${baseUrl.replace(/\/+$/, "")}/health`;
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
33
|
+
try {
|
|
34
|
+
const res = await fetch(url, { method: "GET", signal: controller.signal });
|
|
35
|
+
return res.ok;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Locate the `unbrowse` binary by walking, in order:
|
|
46
|
+
* 1. `UNBROWSE_BIN` env var
|
|
47
|
+
* 2. `require.resolve('unbrowse/package.json')` -> derived `bin/unbrowse-wrapper.mjs`
|
|
48
|
+
* 3. `Bun.which('unbrowse')` if running under Bun
|
|
49
|
+
* Returns null when nothing is wired.
|
|
50
|
+
*/
|
|
51
|
+
export function locateUnbrowseBinary() {
|
|
52
|
+
// 1. Explicit env override.
|
|
53
|
+
const fromEnv = readEnv("UNBROWSE_BIN");
|
|
54
|
+
if (fromEnv && fileExists(fromEnv))
|
|
55
|
+
return fromEnv;
|
|
56
|
+
// 2. require.resolve('unbrowse/package.json') -> bin/unbrowse-wrapper.mjs.
|
|
57
|
+
// Only honor this when the resolved package looks like a real install
|
|
58
|
+
// (the wrapper has a sibling native binary or compiled launcher). A
|
|
59
|
+
// bare workspace tree with no postinstall artifacts would set us up to
|
|
60
|
+
// spawn-and-fail; fall through to PATH lookup in that case.
|
|
61
|
+
try {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
63
|
+
const { createRequire } = require("node:module");
|
|
64
|
+
const requireFn = createRequire(import.meta.url);
|
|
65
|
+
const pkgPath = requireFn.resolve("unbrowse/package.json");
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
67
|
+
const path = require("node:path");
|
|
68
|
+
const binDir = path.join(path.dirname(pkgPath), "bin");
|
|
69
|
+
const wrapper = path.join(binDir, "unbrowse-wrapper.mjs");
|
|
70
|
+
if (fileExists(wrapper) && hasNativeSibling(binDir))
|
|
71
|
+
return wrapper;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// peer dep not installed — fall through
|
|
75
|
+
}
|
|
76
|
+
// 3. Bun.which / PATH lookup. Bun gives us a one-liner; under raw Node
|
|
77
|
+
// we do the PATH walk ourselves so `npx node smoke.mjs` against a
|
|
78
|
+
// globally-installed `unbrowse` works the same as `bun smoke.ts`.
|
|
79
|
+
const bunWhich = globalThis.Bun?.which;
|
|
80
|
+
if (typeof bunWhich === "function") {
|
|
81
|
+
const onPath = bunWhich("unbrowse");
|
|
82
|
+
if (onPath && fileExists(onPath))
|
|
83
|
+
return onPath;
|
|
84
|
+
}
|
|
85
|
+
const fromPath = findOnPath("unbrowse");
|
|
86
|
+
if (fromPath)
|
|
87
|
+
return fromPath;
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
function hasNativeSibling(binDir) {
|
|
91
|
+
try {
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
93
|
+
const fs = require("node:fs");
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
95
|
+
const path = require("node:path");
|
|
96
|
+
return fs.existsSync(path.join(binDir, "unbrowse"))
|
|
97
|
+
|| fs.existsSync(path.join(binDir, "unbrowse.exe"));
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* In-flight spawn promises keyed by port. When two callers race to spawn on
|
|
105
|
+
* the same port, the second one awaits the first's promise instead of
|
|
106
|
+
* launching a competing child that would lose the bind and exit with code=1.
|
|
107
|
+
*
|
|
108
|
+
* Each caller gets its own `RuntimeHandle` view: the *winner* of the race
|
|
109
|
+
* keeps `owned=true` so its `.close()` actually kills the child; subsequent
|
|
110
|
+
* `Unbrowse.local()` callers that joined the in-flight wait get an adopted
|
|
111
|
+
* (`owned=false`) handle so they don't double-kill the shared child.
|
|
112
|
+
*/
|
|
113
|
+
const inFlightSpawns = new Map();
|
|
114
|
+
/**
|
|
115
|
+
* Spawn (or adopt) a co-located `unbrowse` runtime and wait for it to
|
|
116
|
+
* answer `/health`. Returns a `RuntimeHandle` whose `.kill()` tears the
|
|
117
|
+
* child down. Throws `RuntimeUnavailableError` on failure modes.
|
|
118
|
+
*
|
|
119
|
+
* Concurrency: if two callers race on the same port, only one spawn is
|
|
120
|
+
* launched. The second caller awaits the first's promise and gets an
|
|
121
|
+
* adopted (`owned=false`) view of the same handle so it cannot
|
|
122
|
+
* double-kill the child.
|
|
123
|
+
*/
|
|
124
|
+
export async function spawnUnbrowseRuntime(opts = {}) {
|
|
125
|
+
const port = opts.port ?? DEFAULT_PORT;
|
|
126
|
+
// If another caller is mid-spawn on this port, join their promise
|
|
127
|
+
// instead of competing for the bind. The joiner receives an adopted
|
|
128
|
+
// view (owned=false) so the winner's .close() / .kill() is the only
|
|
129
|
+
// one that actually tears the child down.
|
|
130
|
+
const existing = inFlightSpawns.get(port);
|
|
131
|
+
if (existing) {
|
|
132
|
+
const winner = await existing;
|
|
133
|
+
return {
|
|
134
|
+
baseUrl: winner.baseUrl,
|
|
135
|
+
pid: winner.pid,
|
|
136
|
+
kill: async () => { },
|
|
137
|
+
ready: Promise.resolve(),
|
|
138
|
+
owned: false,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const spawnPromise = spawnUnbrowseRuntimeInternal(opts);
|
|
142
|
+
inFlightSpawns.set(port, spawnPromise);
|
|
143
|
+
try {
|
|
144
|
+
return await spawnPromise;
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
// Clear the slot once the spawn settles (success or failure) so a
|
|
148
|
+
// subsequent .close()-then-spawn cycle re-enters the spawn path.
|
|
149
|
+
if (inFlightSpawns.get(port) === spawnPromise) {
|
|
150
|
+
inFlightSpawns.delete(port);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function spawnUnbrowseRuntimeInternal(opts) {
|
|
155
|
+
const port = opts.port ?? DEFAULT_PORT;
|
|
156
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
157
|
+
const readyTimeoutMs = opts.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
|
|
158
|
+
// 1. If a runtime is already alive on the requested port, adopt it.
|
|
159
|
+
if (await probeUnbrowseRuntime(baseUrl, DEFAULT_PROBE_TIMEOUT_MS)) {
|
|
160
|
+
return {
|
|
161
|
+
baseUrl,
|
|
162
|
+
pid: -1,
|
|
163
|
+
kill: async () => { },
|
|
164
|
+
ready: Promise.resolve(),
|
|
165
|
+
owned: false,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
// 2. Locate the binary.
|
|
169
|
+
const binary = opts.binaryPath ?? locateUnbrowseBinary();
|
|
170
|
+
if (!binary || !fileExists(binary)) {
|
|
171
|
+
throw new RuntimeUnavailableError(`unbrowse binary not found${opts.binaryPath ? ` at ${opts.binaryPath}` : ""}. Install with: npm i -g unbrowse`, "binary_missing", port);
|
|
172
|
+
}
|
|
173
|
+
// 3. Spawn via Node's child_process (cross-runtime; Bun shims this).
|
|
174
|
+
// Lazy import keeps the connect-only path tree-shakeable.
|
|
175
|
+
const childProcess = await import("node:child_process");
|
|
176
|
+
const env = {
|
|
177
|
+
...sanitizeEnv(process.env),
|
|
178
|
+
...(opts.env ?? {}),
|
|
179
|
+
PORT: String(port),
|
|
180
|
+
HOST: "127.0.0.1",
|
|
181
|
+
};
|
|
182
|
+
// `unbrowse-wrapper.mjs` is a node script; the global `unbrowse` binary
|
|
183
|
+
// may be a wrapper or a compiled single-binary. Pass `serve` as argv[0]
|
|
184
|
+
// either way — `src/single-binary.ts:106` keys on it, and the wrapper
|
|
185
|
+
// forwards argv unchanged.
|
|
186
|
+
const isJsLauncher = binary.endsWith(".mjs") || binary.endsWith(".js");
|
|
187
|
+
const command = isJsLauncher ? process.execPath : binary;
|
|
188
|
+
const args = isJsLauncher ? [binary, "serve"] : ["serve"];
|
|
189
|
+
// `detached: true` puts the child in its own process group so we can
|
|
190
|
+
// signal the entire group at teardown. The unbrowse wrapper fork-execs
|
|
191
|
+
// a node grandchild that wouldn't otherwise receive our SIGTERM.
|
|
192
|
+
const isPosix = process.platform !== "win32";
|
|
193
|
+
const child = childProcess.spawn(command, args, {
|
|
194
|
+
cwd: opts.cwd,
|
|
195
|
+
env,
|
|
196
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
197
|
+
detached: isPosix,
|
|
198
|
+
});
|
|
199
|
+
// Prevent the detached child from keeping the parent event loop alive.
|
|
200
|
+
if (isPosix)
|
|
201
|
+
child.unref();
|
|
202
|
+
const signalGroup = (signal) => {
|
|
203
|
+
if (child.pid && isPosix) {
|
|
204
|
+
try {
|
|
205
|
+
process.kill(-child.pid, signal);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
catch { /* fall through */ }
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
child.kill(signal);
|
|
212
|
+
}
|
|
213
|
+
catch { /* ignore */ }
|
|
214
|
+
};
|
|
215
|
+
// 4. Poll readiness up to readyTimeoutMs.
|
|
216
|
+
const ready = (async () => {
|
|
217
|
+
const deadline = Date.now() + readyTimeoutMs;
|
|
218
|
+
while (Date.now() < deadline) {
|
|
219
|
+
if (child.exitCode !== null) {
|
|
220
|
+
throw new RuntimeUnavailableError(`unbrowse exited (code=${child.exitCode}) before reaching ready state on port ${port}`, "spawn_failed", port);
|
|
221
|
+
}
|
|
222
|
+
if (await probeUnbrowseRuntime(baseUrl, 250))
|
|
223
|
+
return;
|
|
224
|
+
await sleep(100);
|
|
225
|
+
}
|
|
226
|
+
// Timeout — tear the orphan down and surface the failure.
|
|
227
|
+
signalGroup("SIGTERM");
|
|
228
|
+
throw new RuntimeUnavailableError(`unbrowse runtime on port ${port} did not become ready within ${readyTimeoutMs}ms`, "spawn_failed", port);
|
|
229
|
+
})();
|
|
230
|
+
try {
|
|
231
|
+
await ready;
|
|
232
|
+
}
|
|
233
|
+
catch (e) {
|
|
234
|
+
if (child.exitCode === null)
|
|
235
|
+
signalGroup("SIGTERM");
|
|
236
|
+
throw e;
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
baseUrl,
|
|
240
|
+
pid: child.pid ?? -1,
|
|
241
|
+
kill: async () => {
|
|
242
|
+
if (child.exitCode !== null)
|
|
243
|
+
return;
|
|
244
|
+
signalGroup("SIGTERM");
|
|
245
|
+
// Wait up to 2s for graceful exit; fastify close + browser shutdown
|
|
246
|
+
// can take a moment.
|
|
247
|
+
for (let i = 0; i < 20; i++) {
|
|
248
|
+
if (child.exitCode !== null)
|
|
249
|
+
return;
|
|
250
|
+
await sleep(100);
|
|
251
|
+
}
|
|
252
|
+
if (child.exitCode === null) {
|
|
253
|
+
signalGroup("SIGKILL");
|
|
254
|
+
// Give the kernel a beat to release the listener.
|
|
255
|
+
await sleep(100);
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
ready: Promise.resolve(),
|
|
259
|
+
owned: true,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
// ---- internal helpers ----
|
|
263
|
+
function readEnv(name) {
|
|
264
|
+
const p = globalThis.process;
|
|
265
|
+
if (!p?.env)
|
|
266
|
+
return undefined;
|
|
267
|
+
const v = p.env[name];
|
|
268
|
+
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
269
|
+
}
|
|
270
|
+
function fileExists(p) {
|
|
271
|
+
try {
|
|
272
|
+
// Lazy require keeps this file safe in non-Node runtimes that import
|
|
273
|
+
// only the type definitions. `node:fs` is available wherever spawn
|
|
274
|
+
// matters, so this branch is gated by the caller.
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
276
|
+
const fs = require("node:fs");
|
|
277
|
+
return fs.existsSync(p);
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* PATH walk for raw Node (no Bun.which). Walks `process.env.PATH`, joins each
|
|
285
|
+
* entry with `name` (+ `.exe` on Windows), and returns the first hit. Honors
|
|
286
|
+
* `PATHEXT` on Windows so `unbrowse.cmd` / `unbrowse.bat` resolve too.
|
|
287
|
+
*/
|
|
288
|
+
function findOnPath(name) {
|
|
289
|
+
try {
|
|
290
|
+
const proc = globalThis.process;
|
|
291
|
+
const pathEnv = proc?.env?.PATH ?? proc?.env?.Path;
|
|
292
|
+
if (!pathEnv)
|
|
293
|
+
return null;
|
|
294
|
+
const path = require("node:path");
|
|
295
|
+
const isWin = proc?.platform === "win32";
|
|
296
|
+
const sep = isWin ? ";" : ":";
|
|
297
|
+
const exts = isWin
|
|
298
|
+
? (proc?.env?.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").map((e) => e.toLowerCase())
|
|
299
|
+
: [""];
|
|
300
|
+
for (const dir of pathEnv.split(sep)) {
|
|
301
|
+
if (!dir)
|
|
302
|
+
continue;
|
|
303
|
+
for (const ext of exts) {
|
|
304
|
+
const candidate = path.join(dir, name + ext);
|
|
305
|
+
if (fileExists(candidate))
|
|
306
|
+
return candidate;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function sleep(ms) {
|
|
316
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
317
|
+
}
|
|
318
|
+
function sanitizeEnv(env) {
|
|
319
|
+
const out = {};
|
|
320
|
+
for (const [k, v] of Object.entries(env)) {
|
|
321
|
+
if (typeof v === "string")
|
|
322
|
+
out[k] = v;
|
|
323
|
+
}
|
|
324
|
+
return out;
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/x402.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 payment primitives — typed shapes the SDK and a wallet agree on.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the canonical x402 protocol shape (resource-URL flavor) so a generic
|
|
5
|
+
* x402 wallet client can sign these without an Unbrowse-specific adapter. The
|
|
6
|
+
* backend (`backend/src/middleware/x402-gate.ts:X402PaymentRequirementV2`) is
|
|
7
|
+
* the producer; this is the consumer-side declaration.
|
|
8
|
+
*
|
|
9
|
+
* IMPORTANT: this file MUST NOT import from `./client.js` — keep payment
|
|
10
|
+
* helpers tree-shakeable so callers who do not pay can drop the wallet code.
|
|
11
|
+
*/
|
|
12
|
+
import type { PaymentRequiredError } from "./errors.js";
|
|
13
|
+
/**
|
|
14
|
+
* One acceptable payment route returned by a 402 response. The server may
|
|
15
|
+
* present several (different chains, schemes, prices). The wallet picks one.
|
|
16
|
+
*/
|
|
17
|
+
export interface X402PaymentRequirement {
|
|
18
|
+
/** Settlement scheme, e.g. "exact" for the standard x402 exact-amount path. */
|
|
19
|
+
scheme: string;
|
|
20
|
+
/** Chain identifier, e.g. "base-sepolia", "base", "solana". */
|
|
21
|
+
network: string;
|
|
22
|
+
/** Address that receives the payment. */
|
|
23
|
+
payTo: string;
|
|
24
|
+
/** Atomic-unit amount required (e.g. "1000" for 1000 atomic USDC = $0.001). */
|
|
25
|
+
maxAmountRequired: string;
|
|
26
|
+
/** Resource URL the payment unlocks; agent should not mutate this. */
|
|
27
|
+
resource: string;
|
|
28
|
+
/** Media type expected on success (typically "application/json"). */
|
|
29
|
+
mimeType: string;
|
|
30
|
+
/** Optional human-readable hint. */
|
|
31
|
+
description?: string;
|
|
32
|
+
/** Optional response schema the resource will return after settlement. */
|
|
33
|
+
outputSchema?: unknown;
|
|
34
|
+
/** Scheme-specific extras (token contract address, decimals, EIP-712 domain, etc.). */
|
|
35
|
+
extra?: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Payload format the wallet emits and the gateway verifies. Stored
|
|
39
|
+
* base64-encoded in the `X-PAYMENT` request header.
|
|
40
|
+
*/
|
|
41
|
+
export interface X402PaymentPayload {
|
|
42
|
+
/** Protocol version, currently 1. */
|
|
43
|
+
x402Version: number;
|
|
44
|
+
/** Echoes the scheme of the selected `X402PaymentRequirement`. */
|
|
45
|
+
scheme: string;
|
|
46
|
+
/** Echoes the network of the selected `X402PaymentRequirement`. */
|
|
47
|
+
network: string;
|
|
48
|
+
/** Scheme-specific signed payload (typed-data signature, tx hash, etc.). */
|
|
49
|
+
payload: unknown;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Minimal contract a caller's wallet must satisfy to settle x402 payments.
|
|
53
|
+
* Implementations live outside the SDK (CDP, viem, solana web3.js, x402-axios).
|
|
54
|
+
*/
|
|
55
|
+
export interface WalletLike {
|
|
56
|
+
/** Public address used in `accepts[].payTo` matching when relevant. */
|
|
57
|
+
address: string;
|
|
58
|
+
/**
|
|
59
|
+
* Sign the chosen payment requirement and return the base64-encoded
|
|
60
|
+
* `X-PAYMENT` header value the SDK will attach to the retry request.
|
|
61
|
+
*/
|
|
62
|
+
signX402Payload(req: X402PaymentRequirement): Promise<string>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Settle a `PaymentRequiredError` with the given wallet and replay the
|
|
66
|
+
* request via `retry(paymentHeader)`. Picks the first acceptable
|
|
67
|
+
* requirement from `error.accepts`; the wallet decides whether to sign or
|
|
68
|
+
* reject. If `error.accepts` is empty, the original error propagates.
|
|
69
|
+
*
|
|
70
|
+
* Dep-light by design: no signing libs, no fetch deps — the wallet does
|
|
71
|
+
* the cryptography. The retry's failure (including a second 402)
|
|
72
|
+
* propagates unchanged.
|
|
73
|
+
*/
|
|
74
|
+
export declare function payAndRetry<T>(error: PaymentRequiredError, wallet: WalletLike, retry: (paymentHeader: string) => Promise<T>): Promise<T>;
|
|
75
|
+
//# sourceMappingURL=x402.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x402.d.ts","sourceRoot":"","sources":["../src/x402.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uFAAuF;IACvF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,eAAe,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/D;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC,CAKZ"}
|
package/dist/x402.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 payment primitives — typed shapes the SDK and a wallet agree on.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the canonical x402 protocol shape (resource-URL flavor) so a generic
|
|
5
|
+
* x402 wallet client can sign these without an Unbrowse-specific adapter. The
|
|
6
|
+
* backend (`backend/src/middleware/x402-gate.ts:X402PaymentRequirementV2`) is
|
|
7
|
+
* the producer; this is the consumer-side declaration.
|
|
8
|
+
*
|
|
9
|
+
* IMPORTANT: this file MUST NOT import from `./client.js` — keep payment
|
|
10
|
+
* helpers tree-shakeable so callers who do not pay can drop the wallet code.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Settle a `PaymentRequiredError` with the given wallet and replay the
|
|
14
|
+
* request via `retry(paymentHeader)`. Picks the first acceptable
|
|
15
|
+
* requirement from `error.accepts`; the wallet decides whether to sign or
|
|
16
|
+
* reject. If `error.accepts` is empty, the original error propagates.
|
|
17
|
+
*
|
|
18
|
+
* Dep-light by design: no signing libs, no fetch deps — the wallet does
|
|
19
|
+
* the cryptography. The retry's failure (including a second 402)
|
|
20
|
+
* propagates unchanged.
|
|
21
|
+
*/
|
|
22
|
+
export async function payAndRetry(error, wallet, retry) {
|
|
23
|
+
const requirement = error.accepts?.[0];
|
|
24
|
+
if (!requirement)
|
|
25
|
+
throw error;
|
|
26
|
+
const paymentHeader = await wallet.signX402Payload(requirement);
|
|
27
|
+
return retry(paymentHeader);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=x402.js.map
|
package/dist/x402.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x402.js","sourceRoot":"","sources":["../src/x402.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA0DH;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAA2B,EAC3B,MAAkB,EAClB,KAA4C;IAE5C,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,CAAC,WAAW;QAAE,MAAM,KAAK,CAAC;IAC9B,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IAChE,OAAO,KAAK,CAAC,aAAa,CAAC,CAAC;AAC9B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unbrowse/sdk",
|
|
3
|
+
"version": "6.17.0-preview.6",
|
|
4
|
+
"description": "Thin TypeScript SDK for the canonical Unbrowse local server API.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"test:smoke": "bun test test/integration.smoke.test.ts",
|
|
22
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
23
|
+
"prepack": "npm run build",
|
|
24
|
+
"docs:validate": "node scripts/validate-docs.js",
|
|
25
|
+
"docs:validate:links": "node scripts/validate-links-deep.js",
|
|
26
|
+
"docs:validate:examples": "node scripts/validate-examples.js",
|
|
27
|
+
"docs:validate:quality": "node scripts/validate-content-quality.js",
|
|
28
|
+
"docs:validate:all": "npm run docs:validate && npm run docs:validate:examples && npm run docs:validate:quality",
|
|
29
|
+
"docs:lint": "npm run docs:validate:all",
|
|
30
|
+
"test:docs": "npm run docs:validate:all"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"unbrowse": ">=6.15.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependenciesMeta": {
|
|
36
|
+
"unbrowse": {
|
|
37
|
+
"optional": true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"optionalDependencies": {
|
|
41
|
+
"unbrowse": "^6.15.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"typescript": "^6.0.2"
|
|
45
|
+
}
|
|
46
|
+
}
|