@faremeter/fetch 0.1.0 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faremeter/fetch",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "./dist/src/index.d.ts",
@@ -11,6 +11,9 @@
11
11
  "types": "./dist/src/index.d.ts"
12
12
  }
13
13
  },
14
+ "files": [
15
+ "dist"
16
+ ],
14
17
  "devDependencies": {
15
18
  "@eslint/js": "^9.28.0",
16
19
  "@tapjs/asserts": "^4.0.1",
@@ -26,7 +29,7 @@
26
29
  },
27
30
  "dependencies": {
28
31
  "arktype": "^2.1.20",
29
- "@faremeter/types": "^0.1.0"
32
+ "@faremeter/types": "^0.1.1"
30
33
  },
31
34
  "tap": {
32
35
  "plugin": [
package/src/index.ts DELETED
@@ -1,81 +0,0 @@
1
- import {
2
- type PaymentExecer,
3
- type RequestContext,
4
- type PaymentHandler,
5
- x402PaymentRequiredResponse,
6
- x402PaymentPayload,
7
- isValidationError,
8
- throwValidationError,
9
- } from "@faremeter/types";
10
-
11
- type WrapOptions = {
12
- handlers: PaymentHandler[];
13
- payerChooser?: (execer: PaymentExecer[]) => Promise<PaymentExecer>;
14
- };
15
-
16
- export function chooseFirstAvailable(
17
- possiblePayers: PaymentExecer[],
18
- ): PaymentExecer {
19
- if (possiblePayers.length < 1) {
20
- throw new Error("no applicable payers found");
21
- }
22
-
23
- const payer = possiblePayers[0];
24
-
25
- if (payer === undefined) {
26
- throw new Error("undefined payer found");
27
- }
28
-
29
- return payer;
30
- }
31
-
32
- export function wrap(wrappedFetch: typeof fetch, options: WrapOptions) {
33
- return async (input: RequestInfo | URL, init: RequestInit = {}) => {
34
- const response = await fetch(input, init);
35
-
36
- if (response.status !== 402) {
37
- return response;
38
- }
39
-
40
- const payerChooser = options.payerChooser ?? chooseFirstAvailable;
41
-
42
- const payResp = x402PaymentRequiredResponse(await response.json());
43
-
44
- if (isValidationError(payResp)) {
45
- throwValidationError("couldn't parse payment required response", payResp);
46
- }
47
-
48
- const ctx: RequestContext = {
49
- request: input,
50
- };
51
-
52
- const possiblePayers: PaymentExecer[] = [];
53
-
54
- for (const h of options.handlers) {
55
- possiblePayers.push(...(await h(ctx, payResp.accepts)));
56
- }
57
-
58
- const payer = await payerChooser(possiblePayers);
59
- const payerResult = await payer.exec();
60
-
61
- const payload: x402PaymentPayload = {
62
- x402Version: payResp.x402Version,
63
- scheme: payer.requirements.scheme,
64
- network: payer.requirements.network,
65
- payload: payerResult.payload,
66
- };
67
-
68
- const xPaymentHeader = btoa(JSON.stringify(payload));
69
-
70
- const newInit: RequestInit = {
71
- ...init,
72
- headers: {
73
- ...(init.headers ?? {}),
74
- "X-PAYMENT": xPaymentHeader,
75
- },
76
- };
77
-
78
- const secondResponse = await wrappedFetch(input, newInit);
79
- return secondResponse;
80
- };
81
- }
@@ -1,76 +0,0 @@
1
- #!/usr/bin/env pnpm tsx
2
-
3
- import t from "tap";
4
- import * as fmFetch from "../src/index";
5
- import * as fmTypes from "../src/types";
6
-
7
- import { responseFeeder } from "./mockfetch";
8
-
9
- t.test("basicWrap", async (t) => {
10
- const expectedAccepts = [
11
- {
12
- scheme: "exact",
13
- network: "solana-mainnet",
14
- maxAmountRequired: "1.0",
15
- resource: "http://wherever",
16
- description: "what is a description",
17
- mimeType: "text/plain",
18
- payTo: "someaccount",
19
- maxTimeoutSeconds: 5,
20
- asset: "theasset",
21
- },
22
- ];
23
-
24
- const fakeHandler: fmTypes.PaymentHandler = async (ctx, required) => {
25
- t.equal(required.length, 1);
26
- t.matchOnly(required, expectedAccepts);
27
-
28
- const execers: fmTypes.PaymentExecer[] = [
29
- {
30
- requirements: required[0],
31
- exec: async () => ({
32
- headers: { "X-PAYMENT": "heresmypayment" },
33
- }),
34
- },
35
- ];
36
-
37
- return execers;
38
- };
39
-
40
- const mockFetch = responseFeeder([
41
- async () => {
42
- return new Response(
43
- JSON.stringify({
44
- x402Version: 1,
45
- accepts: expectedAccepts,
46
- }),
47
- {
48
- status: 402,
49
- },
50
- );
51
- },
52
- async (input, init?: RequestInit) => {
53
- if (init === undefined || init.headers === undefined) {
54
- throw new Error("didn't get back request headers");
55
- }
56
-
57
- const headers = init.headers;
58
-
59
- t.match(headers["X-PAYMENT"], "heresmypayment");
60
-
61
- return new Response("mypayload");
62
- },
63
- ]);
64
-
65
- const wrappedFetch = fmFetch.wrap(mockFetch, {
66
- handlers: [fakeHandler],
67
- });
68
-
69
- const res = await wrappedFetch("http://somewhere/something/protected");
70
-
71
- const body = await res.text();
72
- t.match(body, "mypayload");
73
-
74
- t.pass();
75
- t.end();
76
- });
package/test/mockfetch.ts DELETED
@@ -1,20 +0,0 @@
1
- type MockFetchType = typeof fetch;
2
- type MockResponse = Response;
3
-
4
- export function responseFeeder(
5
- responses: (MockFetchType | MockResponse)[],
6
- ): MockFetchType {
7
- return async (input, init?) => {
8
- const t = responses.shift();
9
-
10
- if (t === undefined) {
11
- throw new Error("out of responses to feed");
12
- }
13
-
14
- if (t instanceof Function) {
15
- return t(input, init);
16
- }
17
-
18
- return t;
19
- };
20
- }
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "noEmit": false
6
- },
7
- "include": ["src/**/*"]
8
- }