apinow-sdk 0.28.1 → 0.28.3

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/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export declare const APINOW_SDK_VERSION = "0.28.3";
1
2
  export interface CallOptions {
2
3
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
3
4
  body?: Record<string, any>;
package/dist/index.js CHANGED
@@ -1,7 +1,22 @@
1
1
  import { x402Client, wrapFetchWithPayment } from '@x402/fetch';
2
2
  import { registerExactEvmScheme } from '@x402/evm/exact/client';
3
3
  import { privateKeyToAccount } from 'viem/accounts';
4
- const APINOW_BASE = 'https://apinow.fun';
4
+ const APINOW_BASE = 'https://www.apinow.fun';
5
+ export const APINOW_SDK_VERSION = '0.28.3';
6
+ /**
7
+ * Default base URL. In a browser we prefer the current origin so that
8
+ * signed-auth writes stay same-origin and don't hit a CORS preflight
9
+ * (which then explodes on any apex↔www redirect the host performs).
10
+ * In Node we fall back to the canonical www host.
11
+ */
12
+ function resolveDefaultBaseUrl() {
13
+ if (typeof globalThis !== 'undefined') {
14
+ const w = globalThis.window;
15
+ if (w?.location?.origin)
16
+ return w.location.origin;
17
+ }
18
+ return APINOW_BASE;
19
+ }
5
20
  function isServerConfig(c) {
6
21
  return 'privateKey' in c && typeof c.privateKey === 'string';
7
22
  }
@@ -48,7 +63,7 @@ async function followRedirects(res) {
48
63
  }
49
64
  export function createClient(config) {
50
65
  const server = isServerConfig(config);
51
- const baseUrl = config.baseUrl ?? APINOW_BASE;
66
+ const baseUrl = config.baseUrl ?? resolveDefaultBaseUrl();
52
67
  const customFetch = config.fetch;
53
68
  // Resolve address + signer from whichever config shape the caller passed.
54
69
  const account = server ? privateKeyToAccount(config.privateKey) : null;
@@ -90,9 +105,27 @@ export function createClient(config) {
90
105
  // raw newlines ("Failed to execute 'fetch' on 'Window': Invalid value").
91
106
  // Server parses via regex so space-separated works identically.
92
107
  const message = `APINow auth | address: ${address} | issuedAt: ${issuedAt} | nonce: ${nonce}`;
93
- const signature = await signMessage(message);
108
+ const signature = String(await signMessage(message));
109
+ const authorization = `Bearer ${message}||${signature}||${address}`;
110
+ // Guard against any character that Chrome's fetch() rejects in header
111
+ // values — pre-throw with a readable message rather than letting the
112
+ // browser fail with the opaque "Invalid value" error.
113
+ const bad = /[\r\n\0]/;
114
+ if (bad.test(authorization)) {
115
+ const offender = bad.exec(authorization)?.[0];
116
+ // eslint-disable-next-line no-console
117
+ console.error('[apinow-sdk] bad char in Authorization header', {
118
+ messageLen: message.length,
119
+ sigLen: signature.length,
120
+ offenderCode: offender?.charCodeAt(0),
121
+ messagePreview: message.slice(0, 80),
122
+ });
123
+ throw new Error(`apinow-sdk: signed Authorization header contains a control char (code ${offender?.charCodeAt(0)}). ` +
124
+ `This usually means the wallet signer returned a malformed signature. ` +
125
+ `sigLen=${signature.length} messageLen=${message.length}`);
126
+ }
94
127
  return {
95
- Authorization: `Bearer ${message}||${signature}||${address}`,
128
+ Authorization: authorization,
96
129
  'x-wallet-address': address,
97
130
  };
98
131
  }
@@ -102,15 +135,26 @@ export function createClient(config) {
102
135
  */
103
136
  async function authedFetch(url, init = {}) {
104
137
  const authHeaders = await signAuthHeader();
105
- const res = await fetch(url, {
106
- ...init,
107
- headers: {
108
- ...(init.body ? { 'Content-Type': 'application/json' } : {}),
109
- ...authHeaders,
110
- ...init.headers,
111
- },
112
- });
113
- return res;
138
+ const headers = {
139
+ ...(init.body ? { 'Content-Type': 'application/json' } : {}),
140
+ ...authHeaders,
141
+ ...init.headers,
142
+ };
143
+ try {
144
+ return await fetch(url, { ...init, headers });
145
+ }
146
+ catch (err) {
147
+ // eslint-disable-next-line no-console
148
+ console.error('[apinow-sdk] authedFetch failed', {
149
+ sdkVersion: APINOW_SDK_VERSION,
150
+ url,
151
+ method: init.method || 'GET',
152
+ headerKeys: Object.keys(headers),
153
+ headerLens: Object.fromEntries(Object.entries(headers).map(([k, v]) => [k, String(v).length])),
154
+ err: err?.message,
155
+ });
156
+ throw err;
157
+ }
114
158
  }
115
159
  async function authedJson(url, init = {}) {
116
160
  const res = await authedFetch(url, init);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apinow-sdk",
3
- "version": "0.28.1",
3
+ "version": "0.28.3",
4
4
  "description": "Pay-per-call API SDK & CLI for APINow.fun — endpoints + workflows, wraps x402 so you don't have to",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",