@symbo.ls/fetch 3.14.660 → 3.14.661
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/README.md +1 -1
- package/adapters/rest.js +8 -5
- package/dist/cjs/adapters/rest.js +1 -1
- package/dist/esm/adapters/rest.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -596,7 +596,7 @@ await db.select({ from: '/public/feed', headers: { Authorization: null } }) //
|
|
|
596
596
|
| `'stream'` | the body `ReadableStream`, returned before the body is read (`null` when there is no body) |
|
|
597
597
|
| `'response'` | the raw `Response`, unread (use it when you need the response headers) |
|
|
598
598
|
|
|
599
|
-
A failed response keeps the `{ data, error, status }` contract for every type. The adapter reads the body (JSON by `content-type`, else text) for the message. `error` is its `message` or `error` field, else the status text
|
|
599
|
+
A failed response keeps the `{ data, error, status }` contract for every type. The adapter reads the body (JSON by `content-type`, else text) for the message. `error` is its `message` or `error` field, else the status text, else `HTTP <status>` (an HTTP/2 or HTTP/3 response has no status text), so a failed response always has a truthy `error`. `data` is the error body. With `'response'`, `data` stays the unread `Response`, and the message comes from a copy. An unknown `responseType` throws before the request is sent.
|
|
600
600
|
|
|
601
601
|
Read a streamed (SSE) answer chunk by chunk:
|
|
602
602
|
|
package/adapters/rest.js
CHANGED
|
@@ -58,7 +58,12 @@ const readErrorBody = async (res) => {
|
|
|
58
58
|
return text
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
// The message of a failed response: the body's `message`, else its `error`,
|
|
62
|
+
// else the status text, else `HTTP <status>`. The last one keeps the error
|
|
63
|
+
// truthy — callers test it with `if (error)`, and an HTTP/2 or HTTP/3 response
|
|
64
|
+
// carries no status text at all, so a body without a message would otherwise
|
|
65
|
+
// read as a success.
|
|
66
|
+
const errorMessage = (body, res) => body?.message || body?.error || res.statusText || `HTTP ${res.status}`
|
|
62
67
|
|
|
63
68
|
const request = async (url, options, responseType) => {
|
|
64
69
|
const type = responseType == null ? 'auto' : responseType
|
|
@@ -75,13 +80,11 @@ const request = async (url, options, responseType) => {
|
|
|
75
80
|
|
|
76
81
|
if (!res.ok) {
|
|
77
82
|
// 'response' reads a copy, so the caller still gets the Response unread
|
|
78
|
-
// (Retry-After and the other headers included).
|
|
79
|
-
// error truthy when there is neither a message nor a status text — HTTP/2
|
|
80
|
-
// responses carry no status text at all.
|
|
83
|
+
// (Retry-After and the other headers included).
|
|
81
84
|
const body = await readErrorBody(type === 'response' ? res.clone() : res)
|
|
82
85
|
return {
|
|
83
86
|
data: type === 'response' ? res : body,
|
|
84
|
-
error: errorMessage(body, res)
|
|
87
|
+
error: errorMessage(body, res),
|
|
85
88
|
status: res.status
|
|
86
89
|
}
|
|
87
90
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var $=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var N=(t,e)=>{for(var n in e)$(t,n,{get:e[n],enumerable:!0})},_=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of B(e))!R.call(t,r)&&r!==n&&$(t,r,{get:()=>e[r],enumerable:!(o=x(e,r))||o.enumerable});return t};var H=t=>_($({},"__esModule",{value:!0}),t);var M={};N(M,{restAdapter:()=>j,setup:()=>G});module.exports=H(M);const J=(t,e,n)=>{const o=e&&!e.startsWith("/")?"/":"",r=new URL(`${t}${o}${e}`);if(n)for(const l in n){const u=n[l];u!=null&&r.searchParams.set(l,typeof u=="object"?JSON.stringify(u):u)}return r.toString()},P=t=>Object.prototype.toString.call(t).slice(8,-1),E=["auto","json","text","blob","arrayBuffer","stream","response"],m={json:async t=>{const e=await t.text();return e?JSON.parse(e):null},text:t=>t.text(),blob:t=>t.blob(),arrayBuffer:t=>t.arrayBuffer(),stream:t=>t.body,response:t=>t},I=t=>{const e=t.headers.get("content-type");return e&&e.includes("json")?t.json():t.text()},L=async t=>{const e=await t.text(),n=t.headers.get("content-type");if(e&&n&&n.includes("json"))try{return JSON.parse(e)}catch{}return e},A=(t,e)=>t?.message||t?.error||e.statusText
|
|
1
|
+
"use strict";var $=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var N=(t,e)=>{for(var n in e)$(t,n,{get:e[n],enumerable:!0})},_=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of B(e))!R.call(t,r)&&r!==n&&$(t,r,{get:()=>e[r],enumerable:!(o=x(e,r))||o.enumerable});return t};var H=t=>_($({},"__esModule",{value:!0}),t);var M={};N(M,{restAdapter:()=>j,setup:()=>G});module.exports=H(M);const J=(t,e,n)=>{const o=e&&!e.startsWith("/")?"/":"",r=new URL(`${t}${o}${e}`);if(n)for(const l in n){const u=n[l];u!=null&&r.searchParams.set(l,typeof u=="object"?JSON.stringify(u):u)}return r.toString()},P=t=>Object.prototype.toString.call(t).slice(8,-1),E=["auto","json","text","blob","arrayBuffer","stream","response"],m={json:async t=>{const e=await t.text();return e?JSON.parse(e):null},text:t=>t.text(),blob:t=>t.blob(),arrayBuffer:t=>t.arrayBuffer(),stream:t=>t.body,response:t=>t},I=t=>{const e=t.headers.get("content-type");return e&&e.includes("json")?t.json():t.text()},L=async t=>{const e=await t.text(),n=t.headers.get("content-type");if(e&&n&&n.includes("json"))try{return JSON.parse(e)}catch{}return e},A=(t,e)=>t?.message||t?.error||e.statusText||`HTTP ${e.status}`,p=async(t,e,n)=>{const o=n??"auto";if(!E.includes(o))throw new TypeError(`@symbo.ls/fetch rest: unknown responseType "${o}" \u2014 use one of: ${E.join(", ")}`);const r=await globalThis.fetch(t,e);if(o==="auto"){const l=await I(r);return{data:l,error:r.ok?null:A(l,r),status:r.status}}if(!r.ok){const l=await L(o==="response"?r.clone():r);return{data:o==="response"?r:l,error:A(l,r),status:r.status}}return{data:await m[o](r),error:null,status:r.status}},W=["FormData","Blob","File","URLSearchParams","ReadableStream","ArrayBuffer"],D=t=>t!==null&&typeof t=="object"&&(ArrayBuffer.isView(t)||W.includes(P(t))),F=t=>Array.isArray(t)?t:typeof t.entries=="function"?t.entries():Object.entries(t),O=(...t)=>{const e={},n=new Map;for(const o of t)if(o)for(const[r,l]of F(o)){const u=r.toLowerCase();if(n.has(u)&&delete e[n.get(u)],l==null){n.delete(u);continue}n.set(u,r),e[r]=l}return e},Y={"Content-Type":"application/json"},q={"Content-Type":void 0},G=async({url:t,headers:e,auth:n,fetchOptions:o})=>{if(!t)throw new Error("@symbo.ls/fetch rest: url is required");return j(t,e,n,o)},j=(t,e={},n,o={})=>{let r=n?.token||null;const l=()=>r?{Authorization:`Bearer ${r}`}:null,u=s=>O(e,l(),s),w=s=>({...o,...s}),S=(s,a,i)=>{if(!D(a))return w({method:s,headers:O(e,l(),Y,i),body:JSON.stringify(a)});const c={method:s,headers:O(e,l(),q,i),body:a};return P(a)==="ReadableStream"&&(c.duplex="half"),w(c)},f=(s,a)=>{const i=a||t;if(s&&(s.startsWith("http://")||s.startsWith("https://")))return s;const c=s&&!s.startsWith("/")?"/":"";return`${i}${c}${s||""}`};return{name:"rest",setToken:s=>{r=s},getSession:async()=>{if(!n?.sessionUrl)return r?{token:r}:null;const s=await p(f(n.sessionUrl,n.baseUrl),w({headers:u()}));return s.error?null:s.data},signIn:async s=>{if(!n?.signInUrl)throw new Error("rest: auth.signInUrl not configured");const a=await p(f(n.signInUrl,n.baseUrl),S("POST",s));return a.data?.token&&(r=a.data.token),a},signOut:async()=>(n?.signOutUrl&&await p(f(n.signOutUrl,n.baseUrl),w({method:"POST",headers:u()})),r=null,{error:null}),select:({from:s,params:a,select:i,limit:c,offset:y,order:d,single:b,headers:T,baseUrl:U,responseType:k})=>{const h={...a};return i&&(h.select=i),c&&(h.limit=c),y&&(h.offset=y),b&&(h.single=!0),d&&(typeof d=="string"?h.order=d:Array.isArray(d)?h.order=d.map(g=>`${g.by}:${g.asc===!1?"desc":"asc"}`).join(","):d.by&&(h.order=`${d.by}:${d.asc===!1?"desc":"asc"}`)),p(J(U||t,s||"",h),w({headers:u(T)}),k)},rpc:({from:s,params:a,headers:i,baseUrl:c,responseType:y})=>p(f(`rpc/${s}`,c),S("POST",a,i),y),insert:({from:s,data:a,headers:i,baseUrl:c,responseType:y})=>p(f(s,c),S("POST",a,i),y),update:({from:s,data:a,params:i,method:c,headers:y,baseUrl:d,responseType:b})=>{const T=i?.id||a?.id,U=T?`${s}/${T}`:s;return p(f(U,d),S(c||"PATCH",a,y),b)},upsert:({from:s,data:a,params:i,method:c,headers:y,baseUrl:d,responseType:b})=>{const T=i?.id||a?.id,U=T?`${s}/${T}`:s;return p(f(U,d),S(c||"PUT",a,y),b)},delete:({from:s,params:a,headers:i,baseUrl:c,responseType:y})=>{const d=a?.id,b=d?`${s}/${d}`:s;return p(f(b,c),w({method:"DELETE",headers:u(i)}),y)}}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const j=(t,r
|
|
1
|
+
const j=(t,s,r)=>{const c=s&&!s.startsWith("/")?"/":"",n=new URL(`${t}${c}${s}`);if(r)for(const l in r){const u=r[l];u!=null&&n.searchParams.set(l,typeof u=="object"?JSON.stringify(u):u)}return n.toString()},g=t=>Object.prototype.toString.call(t).slice(8,-1),P=["auto","json","text","blob","arrayBuffer","stream","response"],k={json:async t=>{const s=await t.text();return s?JSON.parse(s):null},text:t=>t.text(),blob:t=>t.blob(),arrayBuffer:t=>t.arrayBuffer(),stream:t=>t.body,response:t=>t},x=t=>{const s=t.headers.get("content-type");return s&&s.includes("json")?t.json():t.text()},B=async t=>{const s=await t.text(),r=t.headers.get("content-type");if(s&&r&&r.includes("json"))try{return JSON.parse(s)}catch{}return s},E=(t,s)=>t?.message||t?.error||s.statusText||`HTTP ${s.status}`,p=async(t,s,r)=>{const c=r??"auto";if(!P.includes(c))throw new TypeError(`@symbo.ls/fetch rest: unknown responseType "${c}" \u2014 use one of: ${P.join(", ")}`);const n=await globalThis.fetch(t,s);if(c==="auto"){const l=await x(n);return{data:l,error:n.ok?null:E(l,n),status:n.status}}if(!n.ok){const l=await B(c==="response"?n.clone():n);return{data:c==="response"?n:l,error:E(l,n),status:n.status}}return{data:await k[c](n),error:null,status:n.status}},R=["FormData","Blob","File","URLSearchParams","ReadableStream","ArrayBuffer"],N=t=>t!==null&&typeof t=="object"&&(ArrayBuffer.isView(t)||R.includes(g(t))),_=t=>Array.isArray(t)?t:typeof t.entries=="function"?t.entries():Object.entries(t),$=(...t)=>{const s={},r=new Map;for(const c of t)if(c)for(const[n,l]of _(c)){const u=n.toLowerCase();if(r.has(u)&&delete s[r.get(u)],l==null){r.delete(u);continue}r.set(u,n),s[n]=l}return s},H={"Content-Type":"application/json"},J={"Content-Type":void 0},L=async({url:t,headers:s,auth:r,fetchOptions:c})=>{if(!t)throw new Error("@symbo.ls/fetch rest: url is required");return m(t,s,r,c)},m=(t,s={},r,c={})=>{let n=r?.token||null;const l=()=>n?{Authorization:`Bearer ${n}`}:null,u=e=>$(s,l(),e),w=e=>({...c,...e}),S=(e,a,o)=>{if(!N(a))return w({method:e,headers:$(s,l(),H,o),body:JSON.stringify(a)});const i={method:e,headers:$(s,l(),J,o),body:a};return g(a)==="ReadableStream"&&(i.duplex="half"),w(i)},f=(e,a)=>{const o=a||t;if(e&&(e.startsWith("http://")||e.startsWith("https://")))return e;const i=e&&!e.startsWith("/")?"/":"";return`${o}${i}${e||""}`};return{name:"rest",setToken:e=>{n=e},getSession:async()=>{if(!r?.sessionUrl)return n?{token:n}:null;const e=await p(f(r.sessionUrl,r.baseUrl),w({headers:u()}));return e.error?null:e.data},signIn:async e=>{if(!r?.signInUrl)throw new Error("rest: auth.signInUrl not configured");const a=await p(f(r.signInUrl,r.baseUrl),S("POST",e));return a.data?.token&&(n=a.data.token),a},signOut:async()=>(r?.signOutUrl&&await p(f(r.signOutUrl,r.baseUrl),w({method:"POST",headers:u()})),n=null,{error:null}),select:({from:e,params:a,select:o,limit:i,offset:y,order:d,single:b,headers:T,baseUrl:U,responseType:A})=>{const h={...a};return o&&(h.select=o),i&&(h.limit=i),y&&(h.offset=y),b&&(h.single=!0),d&&(typeof d=="string"?h.order=d:Array.isArray(d)?h.order=d.map(O=>`${O.by}:${O.asc===!1?"desc":"asc"}`).join(","):d.by&&(h.order=`${d.by}:${d.asc===!1?"desc":"asc"}`)),p(j(U||t,e||"",h),w({headers:u(T)}),A)},rpc:({from:e,params:a,headers:o,baseUrl:i,responseType:y})=>p(f(`rpc/${e}`,i),S("POST",a,o),y),insert:({from:e,data:a,headers:o,baseUrl:i,responseType:y})=>p(f(e,i),S("POST",a,o),y),update:({from:e,data:a,params:o,method:i,headers:y,baseUrl:d,responseType:b})=>{const T=o?.id||a?.id,U=T?`${e}/${T}`:e;return p(f(U,d),S(i||"PATCH",a,y),b)},upsert:({from:e,data:a,params:o,method:i,headers:y,baseUrl:d,responseType:b})=>{const T=o?.id||a?.id,U=T?`${e}/${T}`:e;return p(f(U,d),S(i||"PUT",a,y),b)},delete:({from:e,params:a,headers:o,baseUrl:i,responseType:y})=>{const d=a?.id,b=d?`${e}/${d}`:e;return p(f(b,i),w({method:"DELETE",headers:u(o)}),y)}}};export{m as restAdapter,L as setup};
|