@symbo.ls/fetch 3.14.659 → 3.14.660

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 CHANGED
@@ -572,6 +572,83 @@ await queryClient.prefetchQuery({
572
572
  { fetch: { from: '/users', baseUrl: 'https://api.example.com/auth', headers: { 'X-Custom': 'value' } } }
573
573
  ```
574
574
 
575
+ ### Per-call headers
576
+
577
+ A call's `headers` merge over the adapter's configured `headers` and its token. Names match case-insensitively and the call's value wins, so one call can send its own Bearer token (for example a per-user token). A `null` value removes a configured header. `headers` can be a plain object, a `Headers` instance or an array of `[name, value]` pairs.
578
+
579
+ ```js
580
+ const db = await el.getDB()
581
+ await db.select({ from: '/me', headers: { Authorization: `Bearer ${userToken}` } })
582
+ await db.select({ from: '/public/feed', headers: { Authorization: null } }) // no token on this call
583
+ ```
584
+
585
+ ### `responseType`
586
+
587
+ `responseType` sets how the REST adapter reads the response body. It works on `select`, `rpc`, `insert`, `update`, `upsert` and `delete`, and on the declarative `fetch` options.
588
+
589
+ | Value | `data` on success |
590
+ |-------|-------------------|
591
+ | `'auto'` (default) | JSON when the `content-type` contains `json`, else text |
592
+ | `'json'` | parsed JSON, whatever the `content-type` says (`null` for an empty body) |
593
+ | `'text'` | the body as a string |
594
+ | `'blob'` | a `Blob` — binary bytes and the content type stay intact (audio, xlsx, csv) |
595
+ | `'arrayBuffer'` | an `ArrayBuffer` |
596
+ | `'stream'` | the body `ReadableStream`, returned before the body is read (`null` when there is no body) |
597
+ | `'response'` | the raw `Response`, unread (use it when you need the response headers) |
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. With a type other than `'auto'`, `error` falls back to `HTTP <status>` when both are empty (an HTTP/2 response has no status text). `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
+
601
+ Read a streamed (SSE) answer chunk by chunk:
602
+
603
+ ```js
604
+ const db = await el.getDB()
605
+ const { data: stream, error } = await db.insert({ from: '/ask', data: { question }, responseType: 'stream' })
606
+ if (error) return
607
+ const reader = stream.pipeThrough(new TextDecoderStream()).getReader()
608
+ while (true) {
609
+ const { value, done } = await reader.read()
610
+ if (done) break
611
+ onChunk(value) // 'data: …\n\n' lines, as the server sends them
612
+ }
613
+ ```
614
+
615
+ Download a file as a Blob:
616
+
617
+ ```js
618
+ const { data: blob, error } = await db.select({ from: '/finops/report.xlsx', params: { month: 9 }, responseType: 'blob' })
619
+ if (!error) el.state.update({ reportUrl: URL.createObjectURL(blob) }) // blob.type is the server's content-type
620
+ ```
621
+
622
+ In a declarative `fetch`:
623
+
624
+ ```js
625
+ { state: { answerAudio: null }, fetch: { from: '/voice/answer', responseType: 'blob', as: 'answerAudio' } }
626
+ ```
627
+
628
+ - A `Blob`, `ArrayBuffer`, stream or `Response` goes into state only under `as`, as the value itself. Without `as`, read it in `transform` or `onFetchComplete`.
629
+ - A `'stream'` or `'response'` body can be read once. So these queries are never cached or deduplicated. They send the request again on window focus or reconnect only when `refetchOnWindowFocus: true` or `refetchOnReconnect: true` is set.
630
+
631
+ ### Request bodies
632
+
633
+ The REST adapter sends `data` (`insert`, `update`, `upsert`, `signIn`) and `params` (`rpc`) like this:
634
+
635
+ - `FormData`, `Blob` / `File`, `ArrayBuffer`, typed arrays / `DataView`, `URLSearchParams` and `ReadableStream` go to `fetch` as they are. The adapter sets no `Content-Type` for them, and it drops a configured one. `fetch` then writes the right one: the multipart boundary, the Blob's type or the form-urlencoded type. A per-call `Content-Type` header still applies. A `ReadableStream` is sent with `duplex: 'half'`.
636
+ - Every other value (plain objects, arrays, strings, …) is JSON-encoded with `Content-Type: application/json`, as before.
637
+
638
+ Upload a recording as multipart form data:
639
+
640
+ ```js
641
+ const form = new FormData()
642
+ form.append('audio', recording, 'voice.webm') // a Blob, e.g. from MediaRecorder
643
+ const { data: reply, error } = await db.insert({ from: '/voice', data: form, responseType: 'blob' })
644
+ ```
645
+
646
+ In a declarative mutation, return the `FormData` from `transform`:
647
+
648
+ ```js
649
+ { tag: 'form', fetch: { method: 'insert', from: '/upload', on: 'submit', transform: (data, el) => new FormData(el.node) } }
650
+ ```
651
+
575
652
  ## State inheritance
576
653
 
577
654
  When `state` is a string, the element inherits that key from the parent state. Fetch uses the same string as the default `from` (table name), so declaring `state` is often enough:
@@ -664,14 +741,16 @@ const { data, error } = await db.select({ from: 'articles' })
664
741
 
665
742
  ## Adapter interface
666
743
 
667
- All return `{ data, error }`.
744
+ All return `{ data, error }` (the REST adapter adds `status`).
668
745
 
669
746
  ```js
670
- db.select({ from, select, params, limit, offset, order, single, headers, baseUrl })
671
- db.insert({ from, data, select, headers, baseUrl })
672
- db.update({ from, data, params, method, headers, baseUrl }) // method: 'PUT' | 'PATCH'
673
- db.delete({ from, params, headers, baseUrl })
674
- db.rpc({ from, params, headers, baseUrl })
747
+ db.select({ from, select, params, limit, offset, order, single, headers, baseUrl, responseType })
748
+ db.insert({ from, data, select, headers, baseUrl, responseType })
749
+ db.update({ from, data, params, method, headers, baseUrl, responseType }) // method: 'PUT' | 'PATCH'
750
+ db.upsert({ from, data, params, method, headers, baseUrl, responseType }) // method defaults to 'PUT'
751
+ db.delete({ from, params, headers, baseUrl, responseType })
752
+ db.rpc({ from, params, headers, baseUrl, responseType })
753
+ // responseType (REST): 'auto' | 'json' | 'text' | 'blob' | 'arrayBuffer' | 'stream' | 'response'
675
754
 
676
755
  // Auth (adapter-dependent — implemented by adapters that manage sessions)
677
756
  db.getSession()
@@ -824,8 +903,8 @@ When used as a plugin, fetch hooks into the `create` lifecycle to auto-execute f
824
903
  | `getPreviousPageParam` | function | — | `(firstPage, allPages) => cursor \| null` |
825
904
  | `refetchInterval` | number/string | — | Polling interval |
826
905
  | `refetchIntervalInBackground` | boolean | `false` | Poll when tab hidden |
827
- | `refetchOnWindowFocus` | boolean | `true` | Refetch on tab focus |
828
- | `refetchOnReconnect` | boolean | `true` | Refetch on online |
906
+ | `refetchOnWindowFocus` | boolean | `true` (`false` for `'stream'` / `'response'`) | Refetch on tab focus |
907
+ | `refetchOnReconnect` | boolean | `true` (`false` for `'stream'` / `'response'`) | Refetch on online |
829
908
  | `optimistic` | any/function | — | Optimistic update data |
830
909
  | `invalidates` | string/array/boolean | — | Cache keys to invalidate after mutation |
831
910
  | `onMutate` | function | — | Before mutation fires |
@@ -840,6 +919,7 @@ When used as a plugin, fetch hooks into the `create` lifecycle to auto-execute f
840
919
  | `limit` | number | — | Row limit |
841
920
  | `offset` | number | — | Row offset |
842
921
  | `order` | string/object/array | — | Sort order |
843
- | `headers` | object | — | Per-request headers (REST) |
922
+ | `headers` | object | — | Per-request headers (REST); merged over the configured headers and the token |
844
923
  | `baseUrl` | string | — | Per-request base URL (REST) |
924
+ | `responseType` | string | `'auto'` | How the body is read (REST): `auto`, `json`, `text`, `blob`, `arrayBuffer`, `stream`, `response` |
845
925
  | `lang` | string | auto from context/state | Language override (via params) |
package/adapters/rest.js CHANGED
@@ -14,15 +14,131 @@ const buildUrl = (base, from, params) => {
14
14
  return url.toString()
15
15
  }
16
16
 
17
- const request = async (url, options) => {
18
- const res = await globalThis.fetch(url, options)
17
+ const typeTag = (value) => Object.prototype.toString.call(value).slice(8, -1)
18
+
19
+ // --- Responses ---
20
+ //
21
+ // `responseType` picks how a response body is read. 'auto' is the reader this
22
+ // adapter always had — JSON when the content-type says so, text otherwise — and
23
+ // stays the default. The others return what fetch() gives: a Blob or an
24
+ // ArrayBuffer for binary downloads (audio, xlsx, csv), the body ReadableStream
25
+ // for chunk-by-chunk reads (SSE), or the Response itself. 'stream' and
26
+ // 'response' return WITHOUT reading the body, so each chunk reaches the caller
27
+ // as the server sends it instead of as one string once the stream has ended.
28
+ const RESPONSE_TYPES = ['auto', 'json', 'text', 'blob', 'arrayBuffer', 'stream', 'response']
29
+
30
+ const READERS = {
31
+ // An empty body (204, 205) is null rather than a JSON syntax error.
32
+ json: async (res) => {
33
+ const text = await res.text()
34
+ return text ? JSON.parse(text) : null
35
+ },
36
+ text: (res) => res.text(),
37
+ blob: (res) => res.blob(),
38
+ arrayBuffer: (res) => res.arrayBuffer(),
39
+ stream: (res) => res.body,
40
+ response: (res) => res
41
+ }
42
+
43
+ const readAuto = (res) => {
19
44
  const contentType = res.headers.get('content-type')
20
- const data = contentType && contentType.includes('json')
21
- ? await res.json()
22
- : await res.text()
23
- return { data, error: res.ok ? null : (data?.message || data?.error || res.statusText), status: res.status }
45
+ return contentType && contentType.includes('json') ? res.json() : res.text()
46
+ }
47
+
48
+ // A failed response is read for its message whatever `responseType` asked for:
49
+ // the caller checks `error` first, and a Blob or a stream of an error page
50
+ // carries no message. Unlike 'auto', a body that claims JSON but does not parse
51
+ // stays text instead of throwing.
52
+ const readErrorBody = async (res) => {
53
+ const text = await res.text()
54
+ const contentType = res.headers.get('content-type')
55
+ if (text && contentType && contentType.includes('json')) {
56
+ try { return JSON.parse(text) } catch (_) { /* not JSON after all — keep the text */ }
57
+ }
58
+ return text
59
+ }
60
+
61
+ const errorMessage = (body, res) => body?.message || body?.error || res.statusText
62
+
63
+ const request = async (url, options, responseType) => {
64
+ const type = responseType == null ? 'auto' : responseType
65
+ if (!RESPONSE_TYPES.includes(type)) {
66
+ throw new TypeError(`@symbo.ls/fetch rest: unknown responseType "${type}" — use one of: ${RESPONSE_TYPES.join(', ')}`)
67
+ }
68
+
69
+ const res = await globalThis.fetch(url, options)
70
+
71
+ if (type === 'auto') {
72
+ const data = await readAuto(res)
73
+ return { data, error: res.ok ? null : errorMessage(data, res), status: res.status }
74
+ }
75
+
76
+ if (!res.ok) {
77
+ // 'response' reads a copy, so the caller still gets the Response unread
78
+ // (Retry-After and the other headers included). `HTTP <status>` keeps the
79
+ // error truthy when there is neither a message nor a status text — HTTP/2
80
+ // responses carry no status text at all.
81
+ const body = await readErrorBody(type === 'response' ? res.clone() : res)
82
+ return {
83
+ data: type === 'response' ? res : body,
84
+ error: errorMessage(body, res) || `HTTP ${res.status}`,
85
+ status: res.status
86
+ }
87
+ }
88
+
89
+ return { data: await READERS[type](res), error: null, status: res.status }
24
90
  }
25
91
 
92
+ // --- Request bodies ---
93
+ //
94
+ // fetch() takes these bodies as they are and derives their Content-Type from
95
+ // the value: the multipart boundary for FormData, `blob.type` for a Blob or a
96
+ // File, x-www-form-urlencoded for URLSearchParams. JSON-encoding them turned a
97
+ // FormData upload into the string '{}', and a forced Content-Type loses the
98
+ // multipart boundary. Detection reads the toStringTag, so a value from another
99
+ // realm (an iframe) counts too. Anything else is JSON-encoded, as before.
100
+ const PASS_THROUGH_TAGS = ['FormData', 'Blob', 'File', 'URLSearchParams', 'ReadableStream', 'ArrayBuffer']
101
+
102
+ const isPassThroughBody = (value) =>
103
+ value !== null && typeof value === 'object' &&
104
+ (ArrayBuffer.isView(value) || PASS_THROUGH_TAGS.includes(typeTag(value)))
105
+
106
+ // --- Headers ---
107
+ //
108
+ // Header names are case-insensitive, object keys are not: spreading
109
+ // `{ authorization }` over `{ Authorization }` kept BOTH keys, and fetch()
110
+ // joined them into one "Bearer a, Bearer b" value. Merge by lower-cased name
111
+ // instead — a later source wins and keeps its own spelling, and a null or
112
+ // undefined value removes the header. A source may be any fetch HeadersInit:
113
+ // a plain object, a Headers instance or an array of [name, value] pairs.
114
+ const headerEntries = (source) => {
115
+ if (Array.isArray(source)) return source
116
+ if (typeof source.entries === 'function') return source.entries()
117
+ return Object.entries(source)
118
+ }
119
+
120
+ const mergeHeaders = (...sources) => {
121
+ const merged = {}
122
+ const keyOf = new Map()
123
+ for (const source of sources) {
124
+ if (!source) continue
125
+ for (const [name, value] of headerEntries(source)) {
126
+ const lower = name.toLowerCase()
127
+ if (keyOf.has(lower)) delete merged[keyOf.get(lower)]
128
+ if (value === undefined || value === null) {
129
+ keyOf.delete(lower)
130
+ continue
131
+ }
132
+ keyOf.set(lower, name)
133
+ merged[name] = value
134
+ }
135
+ }
136
+ return merged
137
+ }
138
+
139
+ const JSON_TYPE = { 'Content-Type': 'application/json' }
140
+ const NO_TYPE = { 'Content-Type': undefined }
141
+
26
142
  export const setup = async ({ url, headers, auth, fetchOptions }) => {
27
143
  if (!url) throw new Error('@symbo.ls/fetch rest: url is required')
28
144
  return restAdapter(url, headers, auth, fetchOptions)
@@ -31,16 +147,32 @@ export const setup = async ({ url, headers, auth, fetchOptions }) => {
31
147
  export const restAdapter = (baseUrl, defaultHeaders = {}, authConfig, defaultFetchOptions = {}) => {
32
148
  let token = authConfig?.token || null
33
149
 
34
- const getHeaders = (extra) => {
35
- const h = { ...defaultHeaders, ...extra }
36
- if (token) h.Authorization = `Bearer ${token}`
37
- return h
38
- }
150
+ // Precedence, lowest first: the configured headers, the adapter's token, the
151
+ // body's Content-Type, then the call's own `headers` — so one call can send
152
+ // its own Bearer token (a per-user token) or its own Content-Type.
153
+ const tokenHeader = () => token ? { Authorization: `Bearer ${token}` } : null
39
154
 
40
- const getJsonHeaders = (extra) => ({ ...getHeaders(extra), 'Content-Type': 'application/json' })
155
+ const getHeaders = (extra) => mergeHeaders(defaultHeaders, tokenHeader(), extra)
41
156
 
42
157
  const getFetchOptions = (opts) => ({ ...defaultFetchOptions, ...opts })
43
158
 
159
+ // Options for a request that carries a body. A pass-through body gets no
160
+ // Content-Type from the adapter (NO_TYPE also drops a configured one), so
161
+ // fetch() sets the right one; an explicit per-call Content-Type still wins.
162
+ const withBody = (method, body, extra) => {
163
+ if (!isPassThroughBody(body)) {
164
+ return getFetchOptions({
165
+ method,
166
+ headers: mergeHeaders(defaultHeaders, tokenHeader(), JSON_TYPE, extra),
167
+ body: JSON.stringify(body)
168
+ })
169
+ }
170
+ const opts = { method, headers: mergeHeaders(defaultHeaders, tokenHeader(), NO_TYPE, extra), body }
171
+ // fetch() rejects a streamed request body unless it is half duplex.
172
+ if (typeTag(body) === 'ReadableStream') opts.duplex = 'half'
173
+ return getFetchOptions(opts)
174
+ }
175
+
44
176
  const resolveUrl = (from, base) => {
45
177
  const b = base || baseUrl
46
178
  if (from && (from.startsWith('http://') || from.startsWith('https://'))) return from
@@ -67,11 +199,10 @@ export const restAdapter = (baseUrl, defaultHeaders = {}, authConfig, defaultFet
67
199
 
68
200
  signIn: async (credentials) => {
69
201
  if (!authConfig?.signInUrl) throw new Error('rest: auth.signInUrl not configured')
70
- const result = await request(resolveUrl(authConfig.signInUrl, authConfig.baseUrl), getFetchOptions({
71
- method: 'POST',
72
- headers: getJsonHeaders(),
73
- body: JSON.stringify(credentials)
74
- }))
202
+ const result = await request(
203
+ resolveUrl(authConfig.signInUrl, authConfig.baseUrl),
204
+ withBody('POST', credentials)
205
+ )
75
206
  if (result.data?.token) token = result.data.token
76
207
  return result
77
208
  },
@@ -87,8 +218,9 @@ export const restAdapter = (baseUrl, defaultHeaders = {}, authConfig, defaultFet
87
218
  return { error: null }
88
219
  },
89
220
 
90
- // CRUD
91
- select: ({ from, params, select, limit, offset, order, single, headers, baseUrl: fromBase }) => {
221
+ // CRUD — every call takes `headers` (merged over the configured ones),
222
+ // `baseUrl` and `responseType`.
223
+ select: ({ from, params, select, limit, offset, order, single, headers, baseUrl: fromBase, responseType }) => {
92
224
  const allParams = { ...params }
93
225
  if (select) allParams.select = select
94
226
  if (limit) allParams.limit = limit
@@ -105,32 +237,21 @@ export const restAdapter = (baseUrl, defaultHeaders = {}, authConfig, defaultFet
105
237
  }
106
238
  return request(
107
239
  buildUrl(fromBase || baseUrl, from || '', allParams),
108
- getFetchOptions({ headers: getHeaders(headers) })
240
+ getFetchOptions({ headers: getHeaders(headers) }),
241
+ responseType
109
242
  )
110
243
  },
111
244
 
112
- rpc: ({ from, params, headers, baseUrl: fromBase }) =>
113
- request(resolveUrl(`rpc/${from}`, fromBase), getFetchOptions({
114
- method: 'POST',
115
- headers: getJsonHeaders(headers),
116
- body: JSON.stringify(params)
117
- })),
118
-
119
- insert: ({ from, data, headers, baseUrl: fromBase }) =>
120
- request(resolveUrl(from, fromBase), getFetchOptions({
121
- method: 'POST',
122
- headers: getJsonHeaders(headers),
123
- body: JSON.stringify(data)
124
- })),
125
-
126
- update: ({ from, data, params, method, headers, baseUrl: fromBase }) => {
245
+ rpc: ({ from, params, headers, baseUrl: fromBase, responseType }) =>
246
+ request(resolveUrl(`rpc/${from}`, fromBase), withBody('POST', params, headers), responseType),
247
+
248
+ insert: ({ from, data, headers, baseUrl: fromBase, responseType }) =>
249
+ request(resolveUrl(from, fromBase), withBody('POST', data, headers), responseType),
250
+
251
+ update: ({ from, data, params, method, headers, baseUrl: fromBase, responseType }) => {
127
252
  const id = params?.id || data?.id
128
253
  const path = id ? `${from}/${id}` : from
129
- return request(resolveUrl(path, fromBase), getFetchOptions({
130
- method: method || 'PATCH',
131
- headers: getJsonHeaders(headers),
132
- body: JSON.stringify(data)
133
- }))
254
+ return request(resolveUrl(path, fromBase), withBody(method || 'PATCH', data, headers), responseType)
134
255
  },
135
256
 
136
257
  // Create-or-replace by id. PUT-by-id is the REST-idiomatic upsert (unlike
@@ -138,23 +259,19 @@ export const restAdapter = (baseUrl, defaultHeaders = {}, authConfig, defaultFet
138
259
  // treat "PUT to an id that doesn't exist yet" as a create). Callers that
139
260
  // need different upsert semantics for their backend can still pass
140
261
  // `method` to override.
141
- upsert: ({ from, data, params, method, headers, baseUrl: fromBase }) => {
262
+ upsert: ({ from, data, params, method, headers, baseUrl: fromBase, responseType }) => {
142
263
  const id = params?.id || data?.id
143
264
  const path = id ? `${from}/${id}` : from
144
- return request(resolveUrl(path, fromBase), getFetchOptions({
145
- method: method || 'PUT',
146
- headers: getJsonHeaders(headers),
147
- body: JSON.stringify(data)
148
- }))
265
+ return request(resolveUrl(path, fromBase), withBody(method || 'PUT', data, headers), responseType)
149
266
  },
150
267
 
151
- delete: ({ from, params, headers, baseUrl: fromBase }) => {
268
+ delete: ({ from, params, headers, baseUrl: fromBase, responseType }) => {
152
269
  const id = params?.id
153
270
  const path = id ? `${from}/${id}` : from
154
271
  return request(resolveUrl(path, fromBase), getFetchOptions({
155
272
  method: 'DELETE',
156
273
  headers: getHeaders(headers)
157
- }))
274
+ }), responseType)
158
275
  }
159
276
  }
160
277
 
@@ -1 +1 @@
1
- "use strict";var O=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var J=(a,n)=>{for(var e in n)O(a,e,{get:n[e],enumerable:!0})},N=(a,n,e,c)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of P(n))!k.call(a,r)&&r!==e&&O(a,r,{get:()=>n[r],enumerable:!(c=w(n,r))||c.enumerable});return a};var j=a=>N(O({},"__esModule",{value:!0}),a);var x={};J(x,{restAdapter:()=>S,setup:()=>E});module.exports=j(x);const A=(a,n,e)=>{const c=n&&!n.startsWith("/")?"/":"",r=new URL(`${a}${c}${n}`);if(e)for(const p in e){const d=e[p];d!=null&&r.searchParams.set(p,typeof d=="object"?JSON.stringify(d):d)}return r.toString()},y=async(a,n)=>{const e=await globalThis.fetch(a,n),c=e.headers.get("content-type"),r=c&&c.includes("json")?await e.json():await e.text();return{data:r,error:e.ok?null:r?.message||r?.error||e.statusText,status:e.status}},E=async({url:a,headers:n,auth:e,fetchOptions:c})=>{if(!a)throw new Error("@symbo.ls/fetch rest: url is required");return S(a,n,e,c)},S=(a,n={},e,c={})=>{let r=e?.token||null;const p=t=>{const s={...n,...t};return r&&(s.Authorization=`Bearer ${r}`),s},d=t=>({...p(t),"Content-Type":"application/json"}),u=t=>({...c,...t}),b=(t,s)=>{const i=s||a;if(t&&(t.startsWith("http://")||t.startsWith("https://")))return t;const o=t&&!t.startsWith("/")?"/":"";return`${i}${o}${t||""}`};return{name:"rest",setToken:t=>{r=t},getSession:async()=>{if(!e?.sessionUrl)return r?{token:r}:null;const t=await y(b(e.sessionUrl,e.baseUrl),u({headers:p()}));return t.error?null:t.data},signIn:async t=>{if(!e?.signInUrl)throw new Error("rest: auth.signInUrl not configured");const s=await y(b(e.signInUrl,e.baseUrl),u({method:"POST",headers:d(),body:JSON.stringify(t)}));return s.data?.token&&(r=s.data.token),s},signOut:async()=>(e?.signOutUrl&&await y(b(e.signOutUrl,e.baseUrl),u({method:"POST",headers:p()})),r=null,{error:null}),select:({from:t,params:s,select:i,limit:o,offset:h,order:l,single:$,headers:g,baseUrl:T})=>{const U={...s};return i&&(U.select=i),o&&(U.limit=o),h&&(U.offset=h),$&&(U.single=!0),l&&(typeof l=="string"?U.order=l:Array.isArray(l)?U.order=l.map(f=>`${f.by}:${f.asc===!1?"desc":"asc"}`).join(","):l.by&&(U.order=`${l.by}:${l.asc===!1?"desc":"asc"}`)),y(A(T||a,t||"",U),u({headers:p(g)}))},rpc:({from:t,params:s,headers:i,baseUrl:o})=>y(b(`rpc/${t}`,o),u({method:"POST",headers:d(i),body:JSON.stringify(s)})),insert:({from:t,data:s,headers:i,baseUrl:o})=>y(b(t,o),u({method:"POST",headers:d(i),body:JSON.stringify(s)})),update:({from:t,data:s,params:i,method:o,headers:h,baseUrl:l})=>{const $=i?.id||s?.id,g=$?`${t}/${$}`:t;return y(b(g,l),u({method:o||"PATCH",headers:d(h),body:JSON.stringify(s)}))},upsert:({from:t,data:s,params:i,method:o,headers:h,baseUrl:l})=>{const $=i?.id||s?.id,g=$?`${t}/${$}`:t;return y(b(g,l),u({method:o||"PUT",headers:d(h),body:JSON.stringify(s)}))},delete:({from:t,params:s,headers:i,baseUrl:o})=>{const h=s?.id,l=h?`${t}/${h}`:t;return y(b(l,o),u({method:"DELETE",headers:p(i)}))}}};
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,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)||`HTTP ${r.status}`,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)}}};
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var It=Object.create;var ot=Object.defineProperty;var qt=Object.getOwnPropertyDescriptor;var Ut=Object.getOwnPropertyNames;var zt=Object.getPrototypeOf,jt=Object.prototype.hasOwnProperty;var Gt=(e,t)=>{for(var r in t)ot(e,r,{get:t[r],enumerable:!0})},Ft=(e,t,r,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Ut(t))!jt.call(e,i)&&i!==r&&ot(e,i,{get:()=>t[i],enumerable:!(s=qt(t,i))||s.enumerable});return e};var Et=(e,t,r)=>(r=e!=null?It(zt(e)):{},Ft(t||!e||!e.__esModule?ot(r,"default",{value:e,enumerable:!0}):r,e)),Qt=e=>Ft(ot({},"__esModule",{value:!0}),e);var ne={};Gt(ne,{createAdapter:()=>Jt,default:()=>ae,executeFetch:()=>Tt,fetchPlugin:()=>ie,initAdapterAuth:()=>ut,parseDuration:()=>G,queryClient:()=>oe,registerAdapter:()=>Bt,resolveDb:()=>$t});module.exports=Qt(ne);var n=require("@symbo.ls/utils");const Wt=["select","rpc","insert","update","upsert","delete","subscribe"],xt={rest:()=>import("./adapters/rest.js"),local:()=>import("./adapters/local.js")},it=Symbol.for("@symbo.ls/fetch:CUSTOM_ADAPTERS"),Y=(()=>{if(typeof globalThis<"u"&&globalThis[it])return globalThis[it];const e={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,it,{value:e,writable:!1,configurable:!1,enumerable:!1}),globalThis[it]}catch{}return e})(),at=Symbol.for("@symbo.ls/fetch:PENDING_ADAPTERS"),gt=(()=>{if(typeof globalThis<"u"&&globalThis[at])return globalThis[at];const e={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,at,{value:e,writable:!1,configurable:!1,enumerable:!1}),globalThis[at]}catch{}return e})(),Kt=5e3,Yt=e=>new Promise(t=>{if(Y[e])return t(Y[e]);const r=gt[e]||=[];let s=!1;const i=()=>{s||(s=!0,t(Y[e]||null))};r.push(i),setTimeout(i,Kt)}),Bt=(e,t)=>{Y[e]=t;const r=gt[e];if(r&&r.length){gt[e]=[];for(const s of r)s()}},Jt=e=>{const t={};for(const r of Wt)e[r]&&(t[r]=e[r]);return t.name=e.name||"custom",t},$t=async e=>{if(!e)return null;if(typeof e.select=="function")return e;const{adapter:t,...r}=e,s=typeof t=="string"?t:typeof e=="string"?e:null;if(!s)return null;let i=Y[s]||xt[s];if(!i&&(i=await Yt(s),!i))throw new Error(`Unknown db adapter: "${s}". Use registerAdapter() for adapters with optional deps.`);const o=await i();if(!o||typeof o.setup!="function")throw new Error(`Adapter "${s}" loader returned a module without a setup() function. Got keys: [${Object.keys(o||{}).join(", ")}]. Likely a bundler chunk-resolution issue.`);return o.setup(r)},G=e=>{if(!e)return 0;if(typeof e=="number")return e;const t=e.match(/^(\d+)(ms|s|m|h)$/);if(!t)return 0;const r=parseInt(t[1]),s=t[2];return s==="ms"?r:s==="s"?r*1e3:s==="m"?r*6e4:s==="h"?r*36e5:0},v=new Map,N=new Map,z=new Map,Ht=(e,t,r)=>{if(e.cache?.key)return e.cache.key;const s=Zt(e.params),i=r?`${r}:`:"",o=`${e.from}:${e.method}:${i}${JSON.stringify(s||"")}`;return t?`${o}:${t}`:o},B=e=>v.get(e)||null,J=(e,t,r)=>{const s=v.get(e),i={data:t,error:r,time:Date.now(),stale:!1};v.set(e,i);const o=N.get(e);if(o)for(const a of o)(0,n.isFunction)(a)&&a(i);return i},H=e=>{if(e){const t=v.get(e);t&&(t.stale=!0);return}for(const[,t]of v)t.stale=!0},nt=e=>{if(e){v.delete(e);return}v.clear()},le=(e,t)=>(N.has(e)||N.set(e,new Set),N.get(e).add(t),()=>{const r=N.get(e);r&&(r.delete(t),r.size===0&&N.delete(e))}),St=e=>!e&&e!==!1?{staleTime:6e4,gcTime:3e5}:e===!1?null:e===!0?{staleTime:6e4,gcTime:3e5}:typeof e=="number"?{staleTime:e,gcTime:Math.max(e*5,3e5)}:(0,n.isString)(e)?{staleTime:G(e),gcTime:3e5}:{staleTime:G(e.stale||e.staleTime)||6e4,gcTime:G(e.gc||e.gcTime||e.expire)||3e5,key:e.key};let ft=null;const Vt=()=>{ft||(ft=setInterval(()=>{const e=Date.now();for(const[t,r]of v){const s=N.get(t);!(s&&s.size>0)&&e-r.time>(r.gcTime||3e5)&&v.delete(t)}},3e4),ft.unref&&ft.unref())};Vt();const Dt=3,wt=e=>Math.min(1e3*2**e,3e4),Ct=e=>{const t=e.retry;return t===!1?{count:0}:t===!0||t===void 0?{count:Dt,delay:wt}:typeof t=="number"?{count:t,delay:wt}:{count:t.count??Dt,delay:(0,n.isFunction)(t.delay)?t.delay:typeof t.delay=="number"?()=>t.delay:wt}},Pt=async(e,t)=>{const{count:r,delay:s}=t;let i;for(let o=0;o<=r;o++)try{const a=await e();if(a?.error){if(i=a.error,o<r){const l=(0,n.isFunction)(s)?s(o,i):s;await new Promise(f=>setTimeout(f,l));continue}return a}return a}catch(a){if(i=a,o<r){const l=(0,n.isFunction)(s)?s(o,a):s;await new Promise(f=>setTimeout(f,l));continue}throw a}return{data:null,error:i}},j={focus:new Set,online:new Set};let At=!1;const Xt=()=>{if(At||typeof window>"u")return;At=!0;const e=()=>{for(const r of j.focus)r()},t=()=>{for(const r of j.online)r()};window.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&e()}),window.addEventListener("focus",e),window.addEventListener("online",t)},Lt=(e,t)=>{const r=t.__ref;if(e===!0)return{from:r.__state||t.key,method:"select",query:!0,on:"create"};if((0,n.isString)(e))return{from:e,method:"select",query:!0,on:"create"};if((0,n.isObject)(e)){const s={...e};return s.from=s.from||r.__state||t.key,s.method=s.method||"select",s.on=s.on||"create",s.query===void 0&&(s.query=!0),s}return null},Zt=e=>(!e||(0,n.isFunction)(e),e),ct=(e,t)=>{const r=e?.state?.root||t?.state?.root;if(r?.lang)return r.lang},bt=(e,t)=>{const s=(e?.state?.root||t?.state?.root)?.__fetchScope;return s?String(s):void 0},kt=(e,t,r)=>{let s;if(!e)s=void 0;else if((0,n.isFunction)(e))s=e(t,t.state);else{s={};for(const i in e){const o=e[i];s[i]=(0,n.isFunction)(o)?o(t,t.state):o}}return s},ut=async(e,t)=>{if(!e||e.__authInitialized||(e.__authInitialized=!0,!e.getSession))return;const r=(s,i)=>{const o=t.state?.root;o?.update&&o.update({auth:{user:s,session:i,loading:!1}})};try{const s=await e.getSession();r(s?.user||null,s)}catch(s){console.warn("[fetch] Failed to restore auth session:",s.message)}e.onAuthStateChange&&e.onAuthStateChange((s,i)=>{r(i?.user||null,i)})},vt=async(e,t)=>{if((0,n.isFunction)(e.select))return e.auth!==!1&&await ut(e,t),e;if(e.__resolved)return e.auth!==!1&&await ut(e.__resolved,t),e.__resolved;if(e.__resolving)return e.__resolving;e.__resolving=$t(e);const r=await e.__resolving;return delete e.__resolving,r?(r.auth=e.auth,r.url=e.url,r.key=e.key,e.__resolved=r,t.fetch=r,e.auth!==!1&&await ut(r,t),r):null},D=(e,t,...r)=>{const s=(0,n.isFunction)(e[t])?e[t]:null;s&&s.call(e,...r,e,e.state,e.context)},P=(e,t,r,...s)=>{const i=e&&(0,n.isFunction)(e[r])?e[r]:null;i&&i.call(t,...s,t,t.state,t.context)},V=e=>{const t={},r=e.node;if(!r)return t;if(r.tagName==="FORM"){const i=new FormData(r);for(const[o,a]of i.entries())t[o]=a;return t}const s=r.querySelectorAll("input, textarea, select");for(let i=0;i<s.length;i++){const o=s[i],a=o.name||o.getAttribute("name");a&&(o.type==="checkbox"?t[a]=o.checked:o.type==="file"?t[a]=o.files:t[a]=o.value)}return t},I=(e,t,r,s={})=>{const i=r&&r.startsWith("~/"),o=i&&e.state?.root||e.state;if(o?.update)if(i){const a=r.slice(2);t&&typeof t=="object"&&!Array.isArray(t)&&a in t?o.update(t,{preventFetch:!0,...s}):o.update({[a]:t},{preventFetch:!0,...s})}else{const a=r?{[r]:t}:t;o.update(a,{preventFetch:!0,...s})}},k=(e,t)=>{const r=e?.__ref;r&&(r.__fetchStatus=t,r.__fetching=t.isFetching,r.__fetchError=t.error)},R=async(e,t,r,s={})=>{const i=r?.fetch;if(!i||!t||!t.__ref)return;const o=t.__ref,a=bt(t,r);(!o.__fetchScopeOwner||o.__fetchScopeOwner.scope!==a)&&(o.__fetchScopeOwner={scope:a});const l=o.__fetchScopeOwner,f=()=>t.__ref===o&&o.__fetchScopeOwner===l&&bt(t,r)===a;if(e.enabled===!1||(0,n.isFunction)(e.enabled)&&!e.enabled(t,t.state)||e.skip===!0||(0,n.isFunction)(e.skip)&&e.skip(t,t.state))return;const h=await vt(i,r);if(!h||!f())return;const{from:g,method:S,query:X,params:lt,cache:Z,transform:T,single:dt,auth:Q,fields:q,as:A,limit:$,offset:w,order:W,headers:C,baseUrl:x,page:p,cursor:L,getNextPageParam:K,getPreviousPageParam:tt,infinite:et,placeholderData:F,initialData:E,select:m,keepPreviousData:O}=e;let U=(0,n.isString)(m)?m:void 0;if(X&&(0,n.isFunction)(t.getQuery)){const d=t.getQuery(h.name||"paths");d&&(U=d.select||d.length&&d.join(",")||U)}const rt=kt(lt,t,r),st=St(Z),Mt=Ct(e),ht=ct(t,r),Ot=ht?`:${ht}`:"",Rt=a?`${a}:`:"",_=st?Z?.key||`${g}:${S}:${Rt}${JSON.stringify(rt||"")}${et?":infinite":""}${p?":p"+JSON.stringify(p):""}${Ot}`:null;if(!o.__fetchInitialized&&_&&(o.__fetchInitialized=!0,E!==void 0)){const d=(0,n.isFunction)(E)?E():E;J(_,d,null)}if((S==="select"||S==="rpc")&&_&&st){const d=B(_);if(d&&!d.error){const u=Date.now()-d.time,y=d.stale||u>(st.staleTime||0);let c=d.data;if((0,n.isFunction)(m)&&(c=m(c,t,t.state)),T&&(c=T(c,t,t.state)),!f())return;if(I(t,c,A),!y){k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"});return}}else if(F!==void 0){const u=(0,n.isFunction)(F)?F(t,t.state):F;u!==void 0&&I(t,u,A)}}if(_&&z.has(_)&&!s.force){const d=z.get(_);try{const u=await Promise.race([d,new Promise((y,c)=>setTimeout(()=>c("DEDUP_TIMEOUT"),15e3))]);if(!f())return;if(u?.data!==void 0){let y=u.data;if((0,n.isFunction)(m)&&(y=m(y,t,t.state)),T&&(y=T(y,t,t.state)),!f())return;I(t,y,A),D(t,"onFetchComplete",y),P(e,t,"onFetchComplete",y)}}catch{if(!f())return}return}const Nt=!B(_)?.data;k(t,{isFetching:!0,isLoading:Nt,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),D(t,"onFetchStart"),P(e,t,"onFetchStart");const M=r?.analyze?.emitNetwork,pt=M?typeof performance<"u"?performance.now():Date.now():0;M&&M({phase:"start",mode:"query",from:g,method:S,cacheKey:_,lang:ht});const _t=Pt(async()=>{if(!f())return;if(Q!==!1&&h.auth!==!1&&h.getSession){const c=await h.getSession();if(!f())return;if(Q===!0&&!c){const b={message:"Not authenticated"};return k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:b,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",b),P(e,t,"onFetchError",b),{data:null,error:b}}}const d=h[S];if(!(0,n.isFunction)(d))return{data:null,error:{message:`Method "${S}" not found on adapter`}};const u={from:g,select:U,params:rt,single:dt,limit:$,offset:w,order:W,headers:C,baseUrl:x},y=ct(t,r);if(y&&(u.headers={...u.headers,"Accept-Language":y}),p!==void 0){if((0,n.isObject)(p))p.offset!==void 0&&(u.offset=p.offset),p.limit!==void 0&&(u.limit=p.limit),p.cursor!==void 0&&(u.params={...u.params,cursor:p.cursor});else if(typeof p=="number"){const c=e.pageSize||$||20;u.offset=(p-1)*c,u.limit=c}}if(L!==void 0&&(u.params={...u.params,cursor:L}),S==="insert"||S==="update"||S==="upsert"){let c;if(q===!0||e.on==="submit")c=V(t);else if((0,n.isArray)(q)){const b=V(t);c={};for(const yt of q)c[yt]=b[yt]}else t.state?.parse?c=t.state.parse():(0,n.isObject)(t.state)&&(c={...t.state});T&&(c=T(c,t,t.state)),u.data=c}if(S==="rpc"){let c=rt;if(e.on==="submit"){const b=V(t);c=e.transformParams?e.transformParams(b,t,t.state):b}u.params=c}if(S==="subscribe"){const c=h.subscribe({from:g,params:rt,on:e.subscribeOn},(b,yt,ce)=>{f()&&(I(t,b,A),D(t,"onFetchComplete",b),P(e,t,"onFetchComplete",b))});return f()?(o.__unsubscribe=c,{data:null,error:null,subscribed:!0}):((0,n.isFunction)(c)&&c(),{data:null,error:null,subscribed:!0})}return d(u)},Mt);_&&z.set(_,_t);try{const d=await _t;if(!f()||d?.subscribed)return;const{data:u,error:y}=d||{};if(y){_&&J(_,null,y),k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:y,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",y),P(e,t,"onFetchError",y),M&&M({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:y.message||y,durationMs:(typeof performance<"u"?performance.now():Date.now())-pt});return}if(u!==void 0){if((S==="select"||S==="rpc")&&_){const b=J(_,u,null);b.gcTime=st?.gcTime||3e5}let c=u;if(et&&(0,n.isArray)(u)&&(o.__pages||(o.__pages=[]),s.direction==="previous"?o.__pages.unshift(u):o.__pages.push(u),c=o.__pages.flat(),K&&(o.__nextPageParam=K(u,o.__pages),o.__hasNextPage=o.__nextPageParam!=null),tt&&(o.__prevPageParam=tt(u,o.__pages),o.__hasPreviousPage=o.__prevPageParam!=null)),(0,n.isFunction)(m)&&(c=m(c,t,t.state)),T&&(c=T(c,t,t.state)),!f())return;(!O||c!==void 0)&&I(t,c,A),k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),D(t,"onFetchComplete",c),P(e,t,"onFetchComplete",c),M&&M({phase:"success",mode:"query",ok:!0,from:g,method:S,cacheKey:_,durationMs:(typeof performance<"u"?performance.now():Date.now())-pt})}}catch(d){if(!f())return;k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:d,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",d),P(e,t,"onFetchError",d),M&&M({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:d.message||String(d),durationMs:(typeof performance<"u"?performance.now():Date.now())-pt})}finally{_&&z.get(_)===_t&&z.delete(_)}},te=(e,t,r)=>{const s=e.on,i=t.__ref;i.__fetchListeners||(i.__fetchListeners=[]);const o=e.__runner||R;if(s==="submit"){const a=f=>{f.preventDefault(),o(e,t,r)},l=t.node;l&&(l.addEventListener("submit",a),i.__fetchListeners.push(()=>l.removeEventListener("submit",a)))}else if(s==="click"){const a=()=>o(e,t,r),l=t.node;l&&(l.addEventListener("click",a),i.__fetchListeners.push(()=>l.removeEventListener("click",a)))}else s==="stateChange"&&(i.__fetchOnStateChange=()=>o(e,t,r))},ee=(e,t,r)=>{const s=t.__ref;s.__fetchCleanups||(s.__fetchCleanups=[]),Xt();const i=e.refetchInterval;if(i){const o=typeof i=="number"?i:G(i);if(o>0){const a=setInterval(()=>{(e.refetchIntervalInBackground||typeof document>"u"||document.visibilityState==="visible")&&R(e,t,r,{force:!0})},o);s.__fetchCleanups.push(()=>clearInterval(a))}}if(e.refetchOnWindowFocus!==!1){const o=()=>{const a=ct(t,r),l=bt(t,r),f=Ht(e,a,l),h=B(f),g=St(e.cache);(!h||h.stale||Date.now()-h.time>(g?.staleTime||0))&&R(e,t,r,{force:!0})};j.focus.add(o),s.__fetchCleanups.push(()=>j.focus.delete(o))}if(e.refetchOnReconnect!==!1){const o=()=>R(e,t,r,{force:!0});j.online.add(o),s.__fetchCleanups.push(()=>j.online.delete(o))}},re=(e,t,r)=>{if(!t.optimistic)return null;const s=e.__ref,i=t.as,o=e.state?.parse?e.state.parse():(0,n.isObject)(e.state)?{...e.state}:e.state;s.__optimisticSnapshot=o;const a=(0,n.isFunction)(t.optimistic)?t.optimistic(r,o,e):t.optimistic;return a!==void 0&&I(e,a,i),o},mt=(e,t)=>{const r=e.__ref,s=r.__optimisticSnapshot;s!==void 0&&(I(e,s,t.as),delete r.__optimisticSnapshot)},se=async(e,t,r)=>{const s=r?.fetch;if(!s)return;const i=await vt(s,r);if(!i)return;const o=t.__ref,{method:a,from:l,fields:f,transform:h,as:g,on:S,auth:X,headers:lt,baseUrl:Z,invalidates:T,optimistic:dt,onMutate:Q,onSuccess:q,onError:A,onSettled:$}=e;let w;if(f===!0||S==="submit")w=V(t);else if((0,n.isArray)(f)){const p=V(t);w={};for(const L of f)w[L]=p[L]}else t.state?.parse?w=t.state.parse():(0,n.isObject)(t.state)&&(w={...t.state});h&&(w=h(w,t,t.state)),(0,n.isFunction)(Q)&&Q(w,t,t.state);const W=dt?re(t,e,w):null;o.__fetching=!0,k(t,{isFetching:!0,isLoading:!1,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),D(t,"onFetchStart"),P(e,t,"onFetchStart");const C=r?.analyze?.emitNetwork,x=C?typeof performance<"u"?performance.now():Date.now():0;C&&C({phase:"start",mode:"mutation",from:l,method:a});try{if(X!==!1&&i.auth!==!1&&i.getSession){const m=await i.getSession();if(X===!0&&!m){W!==void 0&&mt(t,e);const O={message:"Not authenticated"};D(t,"onFetchError",O),P(e,t,"onFetchError",O);return}}const p=i[a];if(!(0,n.isFunction)(p))return;const L={from:l,data:w,headers:lt,baseUrl:Z};e.params&&(L.params=kt(e.params,t,r));const K=ct(t,r);K&&(L.headers={...L.headers,"Accept-Language":K});const tt=Ct(e),et=await Pt(()=>p(L),tt),{data:F,error:E}=et||{};if(E){W!==void 0&&mt(t,e),k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:E,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",E),(0,n.isFunction)(A)&&A(E,w,t),(0,n.isFunction)($)&&$(null,E,w,t),C&&C({phase:"error",mode:"mutation",from:l,method:a,error:E.message||String(E),durationMs:(typeof performance<"u"?performance.now():Date.now())-x});return}if(delete o.__optimisticSnapshot,F!==void 0){const m=g?{[g]:F}:F;t.state?.update&&t.state.update(m,{preventFetch:!0})}if(k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),D(t,"onFetchComplete",F),P(e,t,"onFetchComplete",F),(0,n.isFunction)(q)&&q(F,w,t),(0,n.isFunction)($)&&$(F,null,w,t),C&&C({phase:"success",mode:"mutation",ok:!0,from:l,method:a,durationMs:(typeof performance<"u"?performance.now():Date.now())-x}),T){const m=(0,n.isArray)(T)?T:[T];for(const O of m)if(O===!0||O==="*")for(const[U]of v)U.startsWith(l+":")&&H(U);else H(O)}}catch(p){W!==void 0&&mt(t,e),k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:p,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",p),P(e,t,"onFetchError",p),(0,n.isFunction)(A)&&A(p,w,t),(0,n.isFunction)($)&&$(null,p,w,t),C&&C({phase:"error",mode:"mutation",from:l,method:a,error:p.message||String(p),durationMs:(typeof performance<"u"?performance.now():Date.now())-x})}finally{o.__fetching=!1}},Tt=(e,t,r,s)=>{if(!e||!s?.fetch)return;const o=(0,n.exec)(e,t);if(!o)return;const a=(0,n.isArray)(o)?o.map(f=>Lt((0,n.exec)(f,t),t)).filter(Boolean):[Lt(o,t)].filter(Boolean);for(const f of a){const h=f.method==="insert"||f.method==="update"||f.method==="upsert"||f.method==="delete",g=h?se:R;f.on==="create"?g(f,t,s):Promise.resolve().then(()=>{te({...f,__runner:g},t,s)}),!h&&f.on==="create"&&(f.refetchInterval||f.refetchOnWindowFocus!==!1||f.refetchOnReconnect!==!1)&&ee(f,t,s)}const l=t.__ref;l.refetch=f=>{for(const h of a)R(h,t,s,{force:!0,...f})},l.fetchNextPage=()=>{const f=a[0];if(!f||!f.infinite)return;const h=l.__nextPageParam;if(h==null)return;const g={...f,cursor:h};R(g,t,s,{direction:"next",force:!0})},l.fetchPreviousPage=()=>{const f=a[0];if(!f||!f.infinite)return;const h=l.__prevPageParam;if(h==null)return;const g={...f,cursor:h};R(g,t,s,{direction:"previous",force:!0})}},oe={invalidateQueries:e=>{if(!e){H();return}if((0,n.isString)(e))for(const[t]of v)(t.startsWith(e)||t.includes(e))&&H(t);else if((0,n.isArray)(e)){const t=e.join(":");for(const[r]of v)r.includes(t)&&H(r)}},removeQueries:e=>{if(!e){nt();return}if((0,n.isString)(e))for(const[t]of v)(t.startsWith(e)||t.includes(e))&&nt(t)},getQueryData:e=>B(e)?.data??void 0,setQueryData:(e,t)=>{const r=B(e),s=(0,n.isFunction)(t)?t(r?.data):t;J(e,s,null)},prefetchQuery:async(e,t)=>{const r=t?.fetch;if(!r)return;const s=await vt(r,t);if(!s)return;const i=e.cache?.key||`${e.from}:${e.method||"select"}:${JSON.stringify(e.params||"")}`,o=s[e.method||"select"];if(!(0,n.isFunction)(o))return;const a=await o({from:e.from,params:e.params,limit:e.limit,offset:e.offset,order:e.order,single:e.single});if(a?.data!==void 0&&!a?.error){const l=J(i,a.data,null);l.gcTime=St(e.cache)?.gcTime||3e5}return a},getCache:()=>v,clear:()=>nt(),dropNonLang:e=>{if(!e)return;const t=`:${e}`;for(const[r]of v)r.match(/:([a-z]{2,3})$/i)&&(r.endsWith(t)||nt(r))}},ie={name:"fetch",create(e){const t=e.fetch;t&&(e.parent||z.clear(),Tt(t,e,e.state,e.context))}};var ae=Tt;
1
+ "use strict";var zt=Object.create;var at=Object.defineProperty;var jt=Object.getOwnPropertyDescriptor;var Bt=Object.getOwnPropertyNames;var Gt=Object.getPrototypeOf,Qt=Object.prototype.hasOwnProperty;var Wt=(t,e)=>{for(var s in e)at(t,s,{get:e[s],enumerable:!0})},Ct=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Bt(e))!Qt.call(t,o)&&o!==s&&at(t,o,{get:()=>e[o],enumerable:!(r=jt(e,o))||r.enumerable});return t};var Pt=(t,e,s)=>(s=t!=null?zt(Gt(t)):{},Ct(e||!t||!t.__esModule?at(s,"default",{value:t,enumerable:!0}):s,t)),Yt=t=>Ct(at({},"__esModule",{value:!0}),t);var le={};Wt(le,{createAdapter:()=>Xt,default:()=>ue,executeFetch:()=>Dt,fetchPlugin:()=>ce,initAdapterAuth:()=>ht,parseDuration:()=>Y,queryClient:()=>fe,registerAdapter:()=>Ht,resolveDb:()=>Mt});module.exports=Yt(le);var f=require("@symbo.ls/utils");const xt=["select","rpc","insert","update","upsert","delete","subscribe"],Kt={rest:()=>import("./adapters/rest.js"),local:()=>import("./adapters/local.js")},ft=Symbol.for("@symbo.ls/fetch:CUSTOM_ADAPTERS"),V=(()=>{if(typeof globalThis<"u"&&globalThis[ft])return globalThis[ft];const t={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,ft,{value:t,writable:!1,configurable:!1,enumerable:!1}),globalThis[ft]}catch{}return t})(),ct=Symbol.for("@symbo.ls/fetch:PENDING_ADAPTERS"),St=(()=>{if(typeof globalThis<"u"&&globalThis[ct])return globalThis[ct];const t={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,ct,{value:t,writable:!1,configurable:!1,enumerable:!1}),globalThis[ct]}catch{}return t})(),Jt=5e3,Vt=t=>new Promise(e=>{if(V[t])return e(V[t]);const s=St[t]||=[];let r=!1;const o=()=>{r||(r=!0,e(V[t]||null))};s.push(o),setTimeout(o,Jt)}),Ht=(t,e)=>{V[t]=e;const s=St[t];if(s&&s.length){St[t]=[];for(const r of s)r()}},Xt=t=>{const e={};for(const s of xt)t[s]&&(e[s]=t[s]);return e.name=t.name||"custom",e},Mt=async t=>{if(!t)return null;if(typeof t.select=="function")return t;const{adapter:e,...s}=t,r=typeof e=="string"?e:typeof t=="string"?t:null;if(!r)return null;let o=V[r]||Kt[r];if(!o&&(o=await Vt(r),!o))throw new Error(`Unknown db adapter: "${r}". Use registerAdapter() for adapters with optional deps.`);const n=await o();if(!n||typeof n.setup!="function")throw new Error(`Adapter "${r}" loader returned a module without a setup() function. Got keys: [${Object.keys(n||{}).join(", ")}]. Likely a bundler chunk-resolution issue.`);return n.setup(s)},Y=t=>{if(!t)return 0;if(typeof t=="number")return t;const e=t.match(/^(\d+)(ms|s|m|h)$/);if(!e)return 0;const s=parseInt(e[1]),r=e[2];return r==="ms"?s:r==="s"?s*1e3:r==="m"?s*6e4:r==="h"?s*36e5:0},T=new Map,U=new Map,Q=new Map,Zt=(t,e,s)=>{if(t.cache?.key)return t.cache.key;const r=se(t.params),o=s?`${s}:`:"",n=`${t.from}:${t.method}:${o}${JSON.stringify(r||"")}`;return e?`${n}:${e}`:n},H=t=>T.get(t)||null,X=(t,e,s)=>{const r=T.get(t),o={data:e,error:s,time:Date.now(),stale:!1};T.set(t,o);const n=U.get(t);if(n)for(const a of n)(0,f.isFunction)(a)&&a(o);return o},Z=t=>{if(t){const e=T.get(t);e&&(e.stale=!0);return}for(const[,e]of T)e.stale=!0},ut=t=>{if(t){T.delete(t);return}T.clear()},_e=(t,e)=>(U.has(t)||U.set(t,new Set),U.get(t).add(e),()=>{const s=U.get(t);s&&(s.delete(e),s.size===0&&U.delete(t))}),bt=t=>!t&&t!==!1?{staleTime:6e4,gcTime:3e5}:t===!1?null:t===!0?{staleTime:6e4,gcTime:3e5}:typeof t=="number"?{staleTime:t,gcTime:Math.max(t*5,3e5)}:(0,f.isString)(t)?{staleTime:Y(t),gcTime:3e5}:{staleTime:Y(t.stale||t.staleTime)||6e4,gcTime:Y(t.gc||t.gcTime||t.expire)||3e5,key:t.key};let lt=null;const te=()=>{lt||(lt=setInterval(()=>{const t=Date.now();for(const[e,s]of T){const r=U.get(e);!(r&&r.size>0)&&t-s.time>(s.gcTime||3e5)&&T.delete(e)}},3e4),lt.unref&&lt.unref())};te();const At=3,wt=t=>Math.min(1e3*2**t,3e4),Lt=t=>{const e=t.retry;return e===!1?{count:0}:e===!0||e===void 0?{count:At,delay:wt}:typeof e=="number"?{count:e,delay:wt}:{count:e.count??At,delay:(0,f.isFunction)(e.delay)?e.delay:typeof e.delay=="number"?()=>e.delay:wt}},Ot=async(t,e)=>{const{count:s,delay:r}=e;let o;for(let n=0;n<=s;n++)try{const a=await t();if(a?.error){if(o=a.error,n<s){const u=(0,f.isFunction)(r)?r(n,o):r;await new Promise(i=>setTimeout(i,u));continue}return a}return a}catch(a){if(o=a,n<s){const u=(0,f.isFunction)(r)?r(n,a):r;await new Promise(i=>setTimeout(i,u));continue}throw a}return{data:null,error:o}},W={focus:new Set,online:new Set};let Rt=!1;const ee=()=>{if(Rt||typeof window>"u")return;Rt=!0;const t=()=>{for(const s of W.focus)s()},e=()=>{for(const s of W.online)s()};window.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&t()}),window.addEventListener("focus",t),window.addEventListener("online",e)},kt=(t,e)=>{const s=e.__ref;if(t===!0)return{from:s.__state||e.key,method:"select",query:!0,on:"create"};if((0,f.isString)(t))return{from:t,method:"select",query:!0,on:"create"};if((0,f.isObject)(t)){const r={...t};return r.from=r.from||s.__state||e.key,r.method=r.method||"select",r.on=r.on||"create",r.query===void 0&&(r.query=!0),r}return null},se=t=>(!t||(0,f.isFunction)(t),t),dt=(t,e)=>{const s=t?.state?.root||e?.state?.root;if(s?.lang)return s.lang},Tt=(t,e)=>{const r=(t?.state?.root||e?.state?.root)?.__fetchScope;return r?String(r):void 0},$t=(t,e,s)=>{let r;if(!t)r=void 0;else if((0,f.isFunction)(t))r=t(e,e.state);else{r={};for(const o in t){const n=t[o];r[o]=(0,f.isFunction)(n)?n(e,e.state):n}}return r},ht=async(t,e)=>{if(!t||t.__authInitialized||(t.__authInitialized=!0,!t.getSession))return;const s=(r,o)=>{const n=e.state?.root;n?.update&&n.update({auth:{user:r,session:o,loading:!1}})};try{const r=await t.getSession();s(r?.user||null,r)}catch(r){console.warn("[fetch] Failed to restore auth session:",r.message)}t.onAuthStateChange&&t.onAuthStateChange((r,o)=>{s(o?.user||null,o)})},mt=async(t,e)=>{if((0,f.isFunction)(t.select))return t.auth!==!1&&await ht(t,e),t;if(t.__resolved)return t.auth!==!1&&await ht(t.__resolved,e),t.__resolved;if(t.__resolving)return t.__resolving;t.__resolving=Mt(t);const s=await t.__resolving;return delete t.__resolving,s?(s.auth=t.auth,s.url=t.url,s.key=t.key,t.__resolved=s,e.fetch=s,t.auth!==!1&&await ht(s,e),s):null},E=(t,e,...s)=>{const r=(0,f.isFunction)(t[e])?t[e]:null;r&&r.call(t,...s,t,t.state,t.context)},A=(t,e,s,...r)=>{const o=t&&(0,f.isFunction)(t[s])?t[s]:null;o&&o.call(e,...r,e,e.state,e.context)},tt=t=>{const e={},s=t.node;if(!s)return e;if(s.tagName==="FORM"){const o=new FormData(s);for(const[n,a]of o.entries())e[n]=a;return e}const r=s.querySelectorAll("input, textarea, select");for(let o=0;o<r.length;o++){const n=r[o],a=n.name||n.getAttribute("name");a&&(n.type==="checkbox"?e[a]=n.checked:n.type==="file"?e[a]=n.files:e[a]=n.value)}return e},vt=t=>t.responseType==="stream"||t.responseType==="response",re=["Blob","File","ArrayBuffer","ReadableStream","Response"],Ft=t=>t!==null&&typeof t=="object"&&(ArrayBuffer.isView(t)||re.includes(Object.prototype.toString.call(t).slice(8,-1))),q=(t,e,s,r={})=>{if(!s&&Ft(e))return;const o=s&&s.startsWith("~/"),n=o&&t.state?.root||t.state;if(n?.update)if(o){const a=s.slice(2);e&&typeof e=="object"&&!Array.isArray(e)&&!Ft(e)&&a in e?n.update(e,{preventFetch:!0,...r}):n.update({[a]:e},{preventFetch:!0,...r})}else{const a=s?{[s]:e}:e;n.update(a,{preventFetch:!0,...r})}},L=(t,e)=>{const s=t?.__ref;s&&(s.__fetchStatus=e,s.__fetching=e.isFetching,s.__fetchError=e.error)},N=async(t,e,s,r={})=>{const o=s?.fetch;if(!o||!e||!e.__ref)return;const n=e.__ref,a=Tt(e,s);(!n.__fetchScopeOwner||n.__fetchScopeOwner.scope!==a)&&(n.__fetchScopeOwner={scope:a});const u=n.__fetchScopeOwner,i=()=>e.__ref===n&&n.__fetchScopeOwner===u&&Tt(e,s)===a;if(t.enabled===!1||(0,f.isFunction)(t.enabled)&&!t.enabled(e,e.state)||t.skip===!0||(0,f.isFunction)(t.skip)&&t.skip(e,e.state))return;const h=await mt(o,s);if(!h||!i())return;const{from:g,method:S,query:R,params:x,cache:et,transform:D,single:z,auth:st,fields:j,as:k,limit:I,offset:$,order:b,headers:K,baseUrl:C,responseType:B,page:p,cursor:P,getNextPageParam:J,getPreviousPageParam:rt,infinite:nt,placeholderData:v,initialData:F,select:m,keepPreviousData:M}=t;let G=(0,f.isString)(m)?m:void 0;if(R&&(0,f.isFunction)(e.getQuery)){const d=e.getQuery(h.name||"paths");d&&(G=d.select||d.length&&d.join(",")||G)}const ot=$t(x,e,s),it=vt(t)?null:bt(et),Nt=Lt(t),pt=dt(e,s),It=pt?`:${pt}`:"",Ut=a?`${a}:`:"",_=it?et?.key||`${g}:${S}:${Ut}${JSON.stringify(ot||"")}${nt?":infinite":""}${p?":p"+JSON.stringify(p):""}${It}`:null;if(!n.__fetchInitialized&&_&&(n.__fetchInitialized=!0,F!==void 0)){const d=(0,f.isFunction)(F)?F():F;X(_,d,null)}if((S==="select"||S==="rpc")&&_&&it){const d=H(_);if(d&&!d.error){const l=Date.now()-d.time,y=d.stale||l>(it.staleTime||0);let c=d.data;if((0,f.isFunction)(m)&&(c=m(c,e,e.state)),D&&(c=D(c,e,e.state)),!i())return;if(q(e,c,k),!y){L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"});return}}else if(v!==void 0){const l=(0,f.isFunction)(v)?v(e,e.state):v;l!==void 0&&q(e,l,k)}}if(_&&Q.has(_)&&!r.force){const d=Q.get(_);try{const l=await Promise.race([d,new Promise((y,c)=>setTimeout(()=>c("DEDUP_TIMEOUT"),15e3))]);if(!i())return;if(l?.data!==void 0){let y=l.data;if((0,f.isFunction)(m)&&(y=m(y,e,e.state)),D&&(y=D(y,e,e.state)),!i())return;q(e,y,k),E(e,"onFetchComplete",y),A(t,e,"onFetchComplete",y)}}catch{if(!i())return}return}const qt=!H(_)?.data;L(e,{isFetching:!0,isLoading:qt,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),E(e,"onFetchStart"),A(t,e,"onFetchStart");const O=s?.analyze?.emitNetwork,_t=O?typeof performance<"u"?performance.now():Date.now():0;O&&O({phase:"start",mode:"query",from:g,method:S,cacheKey:_,lang:pt});const yt=Ot(async()=>{if(!i())return;if(st!==!1&&h.auth!==!1&&h.getSession){const c=await h.getSession();if(!i())return;if(st===!0&&!c){const w={message:"Not authenticated"};return L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:w,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",w),A(t,e,"onFetchError",w),{data:null,error:w}}}const d=h[S];if(!(0,f.isFunction)(d))return{data:null,error:{message:`Method "${S}" not found on adapter`}};const l={from:g,select:G,params:ot,single:z,limit:I,offset:$,order:b,headers:K,baseUrl:C};B!==void 0&&(l.responseType=B);const y=dt(e,s);if(y&&(l.headers={...l.headers,"Accept-Language":y}),p!==void 0){if((0,f.isObject)(p))p.offset!==void 0&&(l.offset=p.offset),p.limit!==void 0&&(l.limit=p.limit),p.cursor!==void 0&&(l.params={...l.params,cursor:p.cursor});else if(typeof p=="number"){const c=t.pageSize||I||20;l.offset=(p-1)*c,l.limit=c}}if(P!==void 0&&(l.params={...l.params,cursor:P}),S==="insert"||S==="update"||S==="upsert"){let c;if(j===!0||t.on==="submit")c=tt(e);else if((0,f.isArray)(j)){const w=tt(e);c={};for(const gt of j)c[gt]=w[gt]}else e.state?.parse?c=e.state.parse():(0,f.isObject)(e.state)&&(c={...e.state});D&&(c=D(c,e,e.state)),l.data=c}if(S==="rpc"){let c=ot;if(t.on==="submit"){const w=tt(e);c=t.transformParams?t.transformParams(w,e,e.state):w}l.params=c}if(S==="subscribe"){const c=h.subscribe({from:g,params:ot,on:t.subscribeOn},(w,gt,he)=>{i()&&(q(e,w,k),E(e,"onFetchComplete",w),A(t,e,"onFetchComplete",w))});return i()?(n.__unsubscribe=c,{data:null,error:null,subscribed:!0}):((0,f.isFunction)(c)&&c(),{data:null,error:null,subscribed:!0})}return d(l)},Nt);_&&Q.set(_,yt);try{const d=await yt;if(!i()||d?.subscribed)return;const{data:l,error:y}=d||{};if(y){_&&X(_,null,y),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:y,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",y),A(t,e,"onFetchError",y),O&&O({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:y.message||y,durationMs:(typeof performance<"u"?performance.now():Date.now())-_t});return}if(l!==void 0){if((S==="select"||S==="rpc")&&_){const w=X(_,l,null);w.gcTime=it?.gcTime||3e5}let c=l;if(nt&&(0,f.isArray)(l)&&(n.__pages||(n.__pages=[]),r.direction==="previous"?n.__pages.unshift(l):n.__pages.push(l),c=n.__pages.flat(),J&&(n.__nextPageParam=J(l,n.__pages),n.__hasNextPage=n.__nextPageParam!=null),rt&&(n.__prevPageParam=rt(l,n.__pages),n.__hasPreviousPage=n.__prevPageParam!=null)),(0,f.isFunction)(m)&&(c=m(c,e,e.state)),D&&(c=D(c,e,e.state)),!i())return;(!M||c!==void 0)&&q(e,c,k),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),E(e,"onFetchComplete",c),A(t,e,"onFetchComplete",c),O&&O({phase:"success",mode:"query",ok:!0,from:g,method:S,cacheKey:_,durationMs:(typeof performance<"u"?performance.now():Date.now())-_t})}}catch(d){if(!i())return;L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:d,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",d),A(t,e,"onFetchError",d),O&&O({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:d.message||String(d),durationMs:(typeof performance<"u"?performance.now():Date.now())-_t})}finally{_&&Q.get(_)===yt&&Q.delete(_)}},ne=(t,e,s)=>{const r=t.on,o=e.__ref;o.__fetchListeners||(o.__fetchListeners=[]);const n=t.__runner||N;if(r==="submit"){const a=i=>{i.preventDefault(),n(t,e,s)},u=e.node;u&&(u.addEventListener("submit",a),o.__fetchListeners.push(()=>u.removeEventListener("submit",a)))}else if(r==="click"){const a=()=>n(t,e,s),u=e.node;u&&(u.addEventListener("click",a),o.__fetchListeners.push(()=>u.removeEventListener("click",a)))}else r==="stateChange"&&(o.__fetchOnStateChange=()=>n(t,e,s))},oe=(t,e,s)=>{const r=e.__ref;r.__fetchCleanups||(r.__fetchCleanups=[]),ee();const o=t.refetchInterval;if(o){const i=typeof o=="number"?o:Y(o);if(i>0){const h=setInterval(()=>{(t.refetchIntervalInBackground||typeof document>"u"||document.visibilityState==="visible")&&N(t,e,s,{force:!0})},i);r.__fetchCleanups.push(()=>clearInterval(h))}}const n=vt(t),a=t.refetchOnWindowFocus===void 0?!n:t.refetchOnWindowFocus!==!1,u=t.refetchOnReconnect===void 0?!n:t.refetchOnReconnect!==!1;if(a){const i=()=>{const h=dt(e,s),g=Tt(e,s),S=Zt(t,h,g),R=H(S),x=bt(t.cache);(!R||R.stale||Date.now()-R.time>(x?.staleTime||0))&&N(t,e,s,{force:!0})};W.focus.add(i),r.__fetchCleanups.push(()=>W.focus.delete(i))}if(u){const i=()=>N(t,e,s,{force:!0});W.online.add(i),r.__fetchCleanups.push(()=>W.online.delete(i))}},ie=(t,e,s)=>{if(!e.optimistic)return null;const r=t.__ref,o=e.as,n=t.state?.parse?t.state.parse():(0,f.isObject)(t.state)?{...t.state}:t.state;r.__optimisticSnapshot=n;const a=(0,f.isFunction)(e.optimistic)?e.optimistic(s,n,t):e.optimistic;return a!==void 0&&q(t,a,o),n},Et=(t,e)=>{const s=t.__ref,r=s.__optimisticSnapshot;r!==void 0&&(q(t,r,e.as),delete s.__optimisticSnapshot)},ae=async(t,e,s)=>{const r=s?.fetch;if(!r)return;const o=await mt(r,s);if(!o)return;const n=e.__ref,{method:a,from:u,fields:i,transform:h,as:g,on:S,auth:R,headers:x,baseUrl:et,responseType:D,invalidates:z,optimistic:st,onMutate:j,onSuccess:k,onError:I,onSettled:$}=t;let b;if(i===!0||S==="submit")b=tt(e);else if((0,f.isArray)(i)){const p=tt(e);b={};for(const P of i)b[P]=p[P]}else e.state?.parse?b=e.state.parse():(0,f.isObject)(e.state)&&(b={...e.state});h&&(b=h(b,e,e.state)),(0,f.isFunction)(j)&&j(b,e,e.state);const K=st?ie(e,t,b):null;n.__fetching=!0,L(e,{isFetching:!0,isLoading:!1,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),E(e,"onFetchStart"),A(t,e,"onFetchStart");const C=s?.analyze?.emitNetwork,B=C?typeof performance<"u"?performance.now():Date.now():0;C&&C({phase:"start",mode:"mutation",from:u,method:a});try{if(R!==!1&&o.auth!==!1&&o.getSession){const m=await o.getSession();if(R===!0&&!m){K!==void 0&&Et(e,t);const M={message:"Not authenticated"};E(e,"onFetchError",M),A(t,e,"onFetchError",M);return}}const p=o[a];if(!(0,f.isFunction)(p))return;const P={from:u,data:b,headers:x,baseUrl:et};D!==void 0&&(P.responseType=D),t.params&&(P.params=$t(t.params,e,s));const J=dt(e,s);J&&(P.headers={...P.headers,"Accept-Language":J});const rt=Lt(t),nt=await Ot(()=>p(P),rt),{data:v,error:F}=nt||{};if(F){K!==void 0&&Et(e,t),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:F,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",F),(0,f.isFunction)(I)&&I(F,b,e),(0,f.isFunction)($)&&$(null,F,b,e),C&&C({phase:"error",mode:"mutation",from:u,method:a,error:F.message||String(F),durationMs:(typeof performance<"u"?performance.now():Date.now())-B});return}if(delete n.__optimisticSnapshot,v!==void 0&&(g||!Ft(v))){const m=g?{[g]:v}:v;e.state?.update&&e.state.update(m,{preventFetch:!0})}if(L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),E(e,"onFetchComplete",v),A(t,e,"onFetchComplete",v),(0,f.isFunction)(k)&&k(v,b,e),(0,f.isFunction)($)&&$(v,null,b,e),C&&C({phase:"success",mode:"mutation",ok:!0,from:u,method:a,durationMs:(typeof performance<"u"?performance.now():Date.now())-B}),z){const m=(0,f.isArray)(z)?z:[z];for(const M of m)if(M===!0||M==="*")for(const[G]of T)G.startsWith(u+":")&&Z(G);else Z(M)}}catch(p){K!==void 0&&Et(e,t),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:p,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",p),A(t,e,"onFetchError",p),(0,f.isFunction)(I)&&I(p,b,e),(0,f.isFunction)($)&&$(null,p,b,e),C&&C({phase:"error",mode:"mutation",from:u,method:a,error:p.message||String(p),durationMs:(typeof performance<"u"?performance.now():Date.now())-B})}finally{n.__fetching=!1}},Dt=(t,e,s,r)=>{if(!t||!r?.fetch)return;const n=(0,f.exec)(t,e);if(!n)return;const a=(0,f.isArray)(n)?n.map(i=>kt((0,f.exec)(i,e),e)).filter(Boolean):[kt(n,e)].filter(Boolean);for(const i of a){const h=i.method==="insert"||i.method==="update"||i.method==="upsert"||i.method==="delete",g=h?ae:N;i.on==="create"?g(i,e,r):Promise.resolve().then(()=>{ne({...i,__runner:g},e,r)}),!h&&i.on==="create"&&(i.refetchInterval||i.refetchOnWindowFocus!==!1||i.refetchOnReconnect!==!1)&&oe(i,e,r)}const u=e.__ref;u.refetch=i=>{for(const h of a)N(h,e,r,{force:!0,...i})},u.fetchNextPage=()=>{const i=a[0];if(!i||!i.infinite)return;const h=u.__nextPageParam;if(h==null)return;const g={...i,cursor:h};N(g,e,r,{direction:"next",force:!0})},u.fetchPreviousPage=()=>{const i=a[0];if(!i||!i.infinite)return;const h=u.__prevPageParam;if(h==null)return;const g={...i,cursor:h};N(g,e,r,{direction:"previous",force:!0})}},fe={invalidateQueries:t=>{if(!t){Z();return}if((0,f.isString)(t))for(const[e]of T)(e.startsWith(t)||e.includes(t))&&Z(e);else if((0,f.isArray)(t)){const e=t.join(":");for(const[s]of T)s.includes(e)&&Z(s)}},removeQueries:t=>{if(!t){ut();return}if((0,f.isString)(t))for(const[e]of T)(e.startsWith(t)||e.includes(t))&&ut(e)},getQueryData:t=>H(t)?.data??void 0,setQueryData:(t,e)=>{const s=H(t),r=(0,f.isFunction)(e)?e(s?.data):e;X(t,r,null)},prefetchQuery:async(t,e)=>{const s=e?.fetch;if(!s)return;const r=await mt(s,e);if(!r)return;const o=t.cache?.key||`${t.from}:${t.method||"select"}:${JSON.stringify(t.params||"")}`,n=r[t.method||"select"];if(!(0,f.isFunction)(n))return;const a={from:t.from,params:t.params,limit:t.limit,offset:t.offset,order:t.order,single:t.single,headers:t.headers,baseUrl:t.baseUrl};t.responseType!==void 0&&(a.responseType=t.responseType);const u=await n(a);if(u?.data!==void 0&&!u?.error&&!vt(t)){const i=X(o,u.data,null);i.gcTime=bt(t.cache)?.gcTime||3e5}return u},getCache:()=>T,clear:()=>ut(),dropNonLang:t=>{if(!t)return;const e=`:${t}`;for(const[s]of T)s.match(/:([a-z]{2,3})$/i)&&(s.endsWith(e)||ut(s))}},ce={name:"fetch",create(t){const e=t.fetch;e&&(t.parent||Q.clear(),Dt(e,t,t.state,t.context))}};var ue=Dt;
@@ -1 +1 @@
1
- const S=(l,c,e)=>{const y=c&&!c.startsWith("/")?"/":"",r=new URL(`${l}${y}${c}`);if(e)for(const p in e){const o=e[p];o!=null&&r.searchParams.set(p,typeof o=="object"?JSON.stringify(o):o)}return r.toString()},h=async(l,c)=>{const e=await globalThis.fetch(l,c),y=e.headers.get("content-type"),r=y&&y.includes("json")?await e.json():await e.text();return{data:r,error:e.ok?null:r?.message||r?.error||e.statusText,status:e.status}},P=async({url:l,headers:c,auth:e,fetchOptions:y})=>{if(!l)throw new Error("@symbo.ls/fetch rest: url is required");return T(l,c,e,y)},T=(l,c={},e,y={})=>{let r=e?.token||null;const p=t=>{const s={...c,...t};return r&&(s.Authorization=`Bearer ${r}`),s},o=t=>({...p(t),"Content-Type":"application/json"}),d=t=>({...y,...t}),b=(t,s)=>{const n=s||l;if(t&&(t.startsWith("http://")||t.startsWith("https://")))return t;const a=t&&!t.startsWith("/")?"/":"";return`${n}${a}${t||""}`};return{name:"rest",setToken:t=>{r=t},getSession:async()=>{if(!e?.sessionUrl)return r?{token:r}:null;const t=await h(b(e.sessionUrl,e.baseUrl),d({headers:p()}));return t.error?null:t.data},signIn:async t=>{if(!e?.signInUrl)throw new Error("rest: auth.signInUrl not configured");const s=await h(b(e.signInUrl,e.baseUrl),d({method:"POST",headers:o(),body:JSON.stringify(t)}));return s.data?.token&&(r=s.data.token),s},signOut:async()=>(e?.signOutUrl&&await h(b(e.signOutUrl,e.baseUrl),d({method:"POST",headers:p()})),r=null,{error:null}),select:({from:t,params:s,select:n,limit:a,offset:u,order:i,single:$,headers:g,baseUrl:f})=>{const U={...s};return n&&(U.select=n),a&&(U.limit=a),u&&(U.offset=u),$&&(U.single=!0),i&&(typeof i=="string"?U.order=i:Array.isArray(i)?U.order=i.map(O=>`${O.by}:${O.asc===!1?"desc":"asc"}`).join(","):i.by&&(U.order=`${i.by}:${i.asc===!1?"desc":"asc"}`)),h(S(f||l,t||"",U),d({headers:p(g)}))},rpc:({from:t,params:s,headers:n,baseUrl:a})=>h(b(`rpc/${t}`,a),d({method:"POST",headers:o(n),body:JSON.stringify(s)})),insert:({from:t,data:s,headers:n,baseUrl:a})=>h(b(t,a),d({method:"POST",headers:o(n),body:JSON.stringify(s)})),update:({from:t,data:s,params:n,method:a,headers:u,baseUrl:i})=>{const $=n?.id||s?.id,g=$?`${t}/${$}`:t;return h(b(g,i),d({method:a||"PATCH",headers:o(u),body:JSON.stringify(s)}))},upsert:({from:t,data:s,params:n,method:a,headers:u,baseUrl:i})=>{const $=n?.id||s?.id,g=$?`${t}/${$}`:t;return h(b(g,i),d({method:a||"PUT",headers:o(u),body:JSON.stringify(s)}))},delete:({from:t,params:s,headers:n,baseUrl:a})=>{const u=s?.id,i=u?`${t}/${u}`:t;return h(b(i,a),d({method:"DELETE",headers:p(n)}))}}};export{T as restAdapter,P as setup};
1
+ const j=(t,r,n)=>{const c=r&&!r.startsWith("/")?"/":"",s=new URL(`${t}${c}${r}`);if(n)for(const l in n){const u=n[l];u!=null&&s.searchParams.set(l,typeof u=="object"?JSON.stringify(u):u)}return s.toString()},g=t=>Object.prototype.toString.call(t).slice(8,-1),P=["auto","json","text","blob","arrayBuffer","stream","response"],k={json:async t=>{const r=await t.text();return r?JSON.parse(r):null},text:t=>t.text(),blob:t=>t.blob(),arrayBuffer:t=>t.arrayBuffer(),stream:t=>t.body,response:t=>t},x=t=>{const r=t.headers.get("content-type");return r&&r.includes("json")?t.json():t.text()},B=async t=>{const r=await t.text(),n=t.headers.get("content-type");if(r&&n&&n.includes("json"))try{return JSON.parse(r)}catch{}return r},E=(t,r)=>t?.message||t?.error||r.statusText,p=async(t,r,n)=>{const c=n??"auto";if(!P.includes(c))throw new TypeError(`@symbo.ls/fetch rest: unknown responseType "${c}" \u2014 use one of: ${P.join(", ")}`);const s=await globalThis.fetch(t,r);if(c==="auto"){const l=await x(s);return{data:l,error:s.ok?null:E(l,s),status:s.status}}if(!s.ok){const l=await B(c==="response"?s.clone():s);return{data:c==="response"?s:l,error:E(l,s)||`HTTP ${s.status}`,status:s.status}}return{data:await k[c](s),error:null,status:s.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 r={},n=new Map;for(const c of t)if(c)for(const[s,l]of _(c)){const u=s.toLowerCase();if(n.has(u)&&delete r[n.get(u)],l==null){n.delete(u);continue}n.set(u,s),r[s]=l}return r},H={"Content-Type":"application/json"},J={"Content-Type":void 0},L=async({url:t,headers:r,auth:n,fetchOptions:c})=>{if(!t)throw new Error("@symbo.ls/fetch rest: url is required");return m(t,r,n,c)},m=(t,r={},n,c={})=>{let s=n?.token||null;const l=()=>s?{Authorization:`Bearer ${s}`}:null,u=e=>$(r,l(),e),w=e=>({...c,...e}),S=(e,a,o)=>{if(!N(a))return w({method:e,headers:$(r,l(),H,o),body:JSON.stringify(a)});const i={method:e,headers:$(r,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=>{s=e},getSession:async()=>{if(!n?.sessionUrl)return s?{token:s}:null;const e=await p(f(n.sessionUrl,n.baseUrl),w({headers:u()}));return e.error?null:e.data},signIn:async e=>{if(!n?.signInUrl)throw new Error("rest: auth.signInUrl not configured");const a=await p(f(n.signInUrl,n.baseUrl),S("POST",e));return a.data?.token&&(s=a.data.token),a},signOut:async()=>(n?.signOutUrl&&await p(f(n.signOutUrl,n.baseUrl),w({method:"POST",headers:u()})),s=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};
package/dist/esm/index.js CHANGED
@@ -1 +1 @@
1
- import{isArray as z,isFunction as u,isObject as Y,isString as B,exec as Et}from"@symbo.ls/utils";const It=["select","rpc","insert","update","upsert","delete","subscribe"],qt={rest:()=>import("./adapters/rest.js"),local:()=>import("./adapters/local.js")},nt=Symbol.for("@symbo.ls/fetch:CUSTOM_ADAPTERS"),J=(()=>{if(typeof globalThis<"u"&&globalThis[nt])return globalThis[nt];const e={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,nt,{value:e,writable:!1,configurable:!1,enumerable:!1}),globalThis[nt]}catch{}return e})(),ft=Symbol.for("@symbo.ls/fetch:PENDING_ADAPTERS"),St=(()=>{if(typeof globalThis<"u"&&globalThis[ft])return globalThis[ft];const e={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,ft,{value:e,writable:!1,configurable:!1,enumerable:!1}),globalThis[ft]}catch{}return e})(),Ut=5e3,zt=e=>new Promise(t=>{if(J[e])return t(J[e]);const r=St[e]||=[];let s=!1;const i=()=>{s||(s=!0,t(J[e]||null))};r.push(i),setTimeout(i,Ut)}),Zt=(e,t)=>{J[e]=t;const r=St[e];if(r&&r.length){St[e]=[];for(const s of r)s()}},te=e=>{const t={};for(const r of It)e[r]&&(t[r]=e[r]);return t.name=e.name||"custom",t},jt=async e=>{if(!e)return null;if(typeof e.select=="function")return e;const{adapter:t,...r}=e,s=typeof t=="string"?t:typeof e=="string"?e:null;if(!s)return null;let i=J[s]||qt[s];if(!i&&(i=await zt(s),!i))throw new Error(`Unknown db adapter: "${s}". Use registerAdapter() for adapters with optional deps.`);const o=await i();if(!o||typeof o.setup!="function")throw new Error(`Adapter "${s}" loader returned a module without a setup() function. Got keys: [${Object.keys(o||{}).join(", ")}]. Likely a bundler chunk-resolution issue.`);return o.setup(r)},H=e=>{if(!e)return 0;if(typeof e=="number")return e;const t=e.match(/^(\d+)(ms|s|m|h)$/);if(!t)return 0;const r=parseInt(t[1]),s=t[2];return s==="ms"?r:s==="s"?r*1e3:s==="m"?r*6e4:s==="h"?r*36e5:0},v=new Map,N=new Map,j=new Map,Gt=(e,t,r)=>{if(e.cache?.key)return e.cache.key;const s=xt(e.params),i=r?`${r}:`:"",o=`${e.from}:${e.method}:${i}${JSON.stringify(s||"")}`;return t?`${o}:${t}`:o},V=e=>v.get(e)||null,X=(e,t,r)=>{const s=v.get(e),i={data:t,error:r,time:Date.now(),stale:!1};v.set(e,i);const o=N.get(e);if(o)for(const a of o)u(a)&&a(i);return i},Z=e=>{if(e){const t=v.get(e);t&&(t.stale=!0);return}for(const[,t]of v)t.stale=!0},ct=e=>{if(e){v.delete(e);return}v.clear()},ee=(e,t)=>(N.has(e)||N.set(e,new Set),N.get(e).add(t),()=>{const r=N.get(e);r&&(r.delete(t),r.size===0&&N.delete(e))}),wt=e=>!e&&e!==!1?{staleTime:6e4,gcTime:3e5}:e===!1?null:e===!0?{staleTime:6e4,gcTime:3e5}:typeof e=="number"?{staleTime:e,gcTime:Math.max(e*5,3e5)}:B(e)?{staleTime:H(e),gcTime:3e5}:{staleTime:H(e.stale||e.staleTime)||6e4,gcTime:H(e.gc||e.gcTime||e.expire)||3e5,key:e.key};let ut=null;const Qt=()=>{ut||(ut=setInterval(()=>{const e=Date.now();for(const[t,r]of v){const s=N.get(t);!(s&&s.size>0)&&e-r.time>(r.gcTime||3e5)&&v.delete(t)}},3e4),ut.unref&&ut.unref())};Qt();const Dt=3,bt=e=>Math.min(1e3*2**e,3e4),Ct=e=>{const t=e.retry;return t===!1?{count:0}:t===!0||t===void 0?{count:Dt,delay:bt}:typeof t=="number"?{count:t,delay:bt}:{count:t.count??Dt,delay:u(t.delay)?t.delay:typeof t.delay=="number"?()=>t.delay:bt}},Pt=async(e,t)=>{const{count:r,delay:s}=t;let i;for(let o=0;o<=r;o++)try{const a=await e();if(a?.error){if(i=a.error,o<r){const l=u(s)?s(o,i):s;await new Promise(n=>setTimeout(n,l));continue}return a}return a}catch(a){if(i=a,o<r){const l=u(s)?s(o,a):s;await new Promise(n=>setTimeout(n,l));continue}throw a}return{data:null,error:i}},G={focus:new Set,online:new Set};let At=!1;const Wt=()=>{if(At||typeof window>"u")return;At=!0;const e=()=>{for(const r of G.focus)r()},t=()=>{for(const r of G.online)r()};window.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&e()}),window.addEventListener("focus",e),window.addEventListener("online",t)},Lt=(e,t)=>{const r=t.__ref;if(e===!0)return{from:r.__state||t.key,method:"select",query:!0,on:"create"};if(B(e))return{from:e,method:"select",query:!0,on:"create"};if(Y(e)){const s={...e};return s.from=s.from||r.__state||t.key,s.method=s.method||"select",s.on=s.on||"create",s.query===void 0&&(s.query=!0),s}return null},xt=e=>(!e||u(e),e),lt=(e,t)=>{const r=e?.state?.root||t?.state?.root;if(r?.lang)return r.lang},vt=(e,t)=>{const s=(e?.state?.root||t?.state?.root)?.__fetchScope;return s?String(s):void 0},kt=(e,t,r)=>{let s;if(!e)s=void 0;else if(u(e))s=e(t,t.state);else{s={};for(const i in e){const o=e[i];s[i]=u(o)?o(t,t.state):o}}return s},mt=async(e,t)=>{if(!e||e.__authInitialized||(e.__authInitialized=!0,!e.getSession))return;const r=(s,i)=>{const o=t.state?.root;o?.update&&o.update({auth:{user:s,session:i,loading:!1}})};try{const s=await e.getSession();r(s?.user||null,s)}catch(s){console.warn("[fetch] Failed to restore auth session:",s.message)}e.onAuthStateChange&&e.onAuthStateChange((s,i)=>{r(i?.user||null,i)})},Tt=async(e,t)=>{if(u(e.select))return e.auth!==!1&&await mt(e,t),e;if(e.__resolved)return e.auth!==!1&&await mt(e.__resolved,t),e.__resolved;if(e.__resolving)return e.__resolving;e.__resolving=jt(e);const r=await e.__resolving;return delete e.__resolving,r?(r.auth=e.auth,r.url=e.url,r.key=e.key,e.__resolved=r,t.fetch=r,e.auth!==!1&&await mt(r,t),r):null},D=(e,t,...r)=>{const s=u(e[t])?e[t]:null;s&&s.call(e,...r,e,e.state,e.context)},P=(e,t,r,...s)=>{const i=e&&u(e[r])?e[r]:null;i&&i.call(t,...s,t,t.state,t.context)},tt=e=>{const t={},r=e.node;if(!r)return t;if(r.tagName==="FORM"){const i=new FormData(r);for(const[o,a]of i.entries())t[o]=a;return t}const s=r.querySelectorAll("input, textarea, select");for(let i=0;i<s.length;i++){const o=s[i],a=o.name||o.getAttribute("name");a&&(o.type==="checkbox"?t[a]=o.checked:o.type==="file"?t[a]=o.files:t[a]=o.value)}return t},I=(e,t,r,s={})=>{const i=r&&r.startsWith("~/"),o=i&&e.state?.root||e.state;if(o?.update)if(i){const a=r.slice(2);t&&typeof t=="object"&&!Array.isArray(t)&&a in t?o.update(t,{preventFetch:!0,...s}):o.update({[a]:t},{preventFetch:!0,...s})}else{const a=r?{[r]:t}:t;o.update(a,{preventFetch:!0,...s})}},k=(e,t)=>{const r=e?.__ref;r&&(r.__fetchStatus=t,r.__fetching=t.isFetching,r.__fetchError=t.error)},R=async(e,t,r,s={})=>{const i=r?.fetch;if(!i||!t||!t.__ref)return;const o=t.__ref,a=vt(t,r);(!o.__fetchScopeOwner||o.__fetchScopeOwner.scope!==a)&&(o.__fetchScopeOwner={scope:a});const l=o.__fetchScopeOwner,n=()=>t.__ref===o&&o.__fetchScopeOwner===l&&vt(t,r)===a;if(e.enabled===!1||u(e.enabled)&&!e.enabled(t,t.state)||e.skip===!0||u(e.skip)&&e.skip(t,t.state))return;const h=await Tt(i,r);if(!h||!n())return;const{from:g,method:S,query:et,params:dt,cache:rt,transform:T,single:ht,auth:Q,fields:q,as:A,limit:$,offset:w,order:W,headers:C,baseUrl:x,page:p,cursor:L,getNextPageParam:K,getPreviousPageParam:st,infinite:ot,placeholderData:F,initialData:E,select:m,keepPreviousData:O}=e;let U=B(m)?m:void 0;if(et&&u(t.getQuery)){const d=t.getQuery(h.name||"paths");d&&(U=d.select||d.length&&d.join(",")||U)}const it=kt(dt,t,r),at=wt(rt),Mt=Ct(e),pt=lt(t,r),Ot=pt?`:${pt}`:"",Rt=a?`${a}:`:"",_=at?rt?.key||`${g}:${S}:${Rt}${JSON.stringify(it||"")}${ot?":infinite":""}${p?":p"+JSON.stringify(p):""}${Ot}`:null;if(!o.__fetchInitialized&&_&&(o.__fetchInitialized=!0,E!==void 0)){const d=u(E)?E():E;X(_,d,null)}if((S==="select"||S==="rpc")&&_&&at){const d=V(_);if(d&&!d.error){const c=Date.now()-d.time,y=d.stale||c>(at.staleTime||0);let f=d.data;if(u(m)&&(f=m(f,t,t.state)),T&&(f=T(f,t,t.state)),!n())return;if(I(t,f,A),!y){k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"});return}}else if(F!==void 0){const c=u(F)?F(t,t.state):F;c!==void 0&&I(t,c,A)}}if(_&&j.has(_)&&!s.force){const d=j.get(_);try{const c=await Promise.race([d,new Promise((y,f)=>setTimeout(()=>f("DEDUP_TIMEOUT"),15e3))]);if(!n())return;if(c?.data!==void 0){let y=c.data;if(u(m)&&(y=m(y,t,t.state)),T&&(y=T(y,t,t.state)),!n())return;I(t,y,A),D(t,"onFetchComplete",y),P(e,t,"onFetchComplete",y)}}catch{if(!n())return}return}const Nt=!V(_)?.data;k(t,{isFetching:!0,isLoading:Nt,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),D(t,"onFetchStart"),P(e,t,"onFetchStart");const M=r?.analyze?.emitNetwork,_t=M?typeof performance<"u"?performance.now():Date.now():0;M&&M({phase:"start",mode:"query",from:g,method:S,cacheKey:_,lang:pt});const yt=Pt(async()=>{if(!n())return;if(Q!==!1&&h.auth!==!1&&h.getSession){const f=await h.getSession();if(!n())return;if(Q===!0&&!f){const b={message:"Not authenticated"};return k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:b,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",b),P(e,t,"onFetchError",b),{data:null,error:b}}}const d=h[S];if(!u(d))return{data:null,error:{message:`Method "${S}" not found on adapter`}};const c={from:g,select:U,params:it,single:ht,limit:$,offset:w,order:W,headers:C,baseUrl:x},y=lt(t,r);if(y&&(c.headers={...c.headers,"Accept-Language":y}),p!==void 0){if(Y(p))p.offset!==void 0&&(c.offset=p.offset),p.limit!==void 0&&(c.limit=p.limit),p.cursor!==void 0&&(c.params={...c.params,cursor:p.cursor});else if(typeof p=="number"){const f=e.pageSize||$||20;c.offset=(p-1)*f,c.limit=f}}if(L!==void 0&&(c.params={...c.params,cursor:L}),S==="insert"||S==="update"||S==="upsert"){let f;if(q===!0||e.on==="submit")f=tt(t);else if(z(q)){const b=tt(t);f={};for(const gt of q)f[gt]=b[gt]}else t.state?.parse?f=t.state.parse():Y(t.state)&&(f={...t.state});T&&(f=T(f,t,t.state)),c.data=f}if(S==="rpc"){let f=it;if(e.on==="submit"){const b=tt(t);f=e.transformParams?e.transformParams(b,t,t.state):b}c.params=f}if(S==="subscribe"){const f=h.subscribe({from:g,params:it,on:e.subscribeOn},(b,gt,Vt)=>{n()&&(I(t,b,A),D(t,"onFetchComplete",b),P(e,t,"onFetchComplete",b))});return n()?(o.__unsubscribe=f,{data:null,error:null,subscribed:!0}):(u(f)&&f(),{data:null,error:null,subscribed:!0})}return d(c)},Mt);_&&j.set(_,yt);try{const d=await yt;if(!n()||d?.subscribed)return;const{data:c,error:y}=d||{};if(y){_&&X(_,null,y),k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:y,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",y),P(e,t,"onFetchError",y),M&&M({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:y.message||y,durationMs:(typeof performance<"u"?performance.now():Date.now())-_t});return}if(c!==void 0){if((S==="select"||S==="rpc")&&_){const b=X(_,c,null);b.gcTime=at?.gcTime||3e5}let f=c;if(ot&&z(c)&&(o.__pages||(o.__pages=[]),s.direction==="previous"?o.__pages.unshift(c):o.__pages.push(c),f=o.__pages.flat(),K&&(o.__nextPageParam=K(c,o.__pages),o.__hasNextPage=o.__nextPageParam!=null),st&&(o.__prevPageParam=st(c,o.__pages),o.__hasPreviousPage=o.__prevPageParam!=null)),u(m)&&(f=m(f,t,t.state)),T&&(f=T(f,t,t.state)),!n())return;(!O||f!==void 0)&&I(t,f,A),k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),D(t,"onFetchComplete",f),P(e,t,"onFetchComplete",f),M&&M({phase:"success",mode:"query",ok:!0,from:g,method:S,cacheKey:_,durationMs:(typeof performance<"u"?performance.now():Date.now())-_t})}}catch(d){if(!n())return;k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:d,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",d),P(e,t,"onFetchError",d),M&&M({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:d.message||String(d),durationMs:(typeof performance<"u"?performance.now():Date.now())-_t})}finally{_&&j.get(_)===yt&&j.delete(_)}},Kt=(e,t,r)=>{const s=e.on,i=t.__ref;i.__fetchListeners||(i.__fetchListeners=[]);const o=e.__runner||R;if(s==="submit"){const a=n=>{n.preventDefault(),o(e,t,r)},l=t.node;l&&(l.addEventListener("submit",a),i.__fetchListeners.push(()=>l.removeEventListener("submit",a)))}else if(s==="click"){const a=()=>o(e,t,r),l=t.node;l&&(l.addEventListener("click",a),i.__fetchListeners.push(()=>l.removeEventListener("click",a)))}else s==="stateChange"&&(i.__fetchOnStateChange=()=>o(e,t,r))},Yt=(e,t,r)=>{const s=t.__ref;s.__fetchCleanups||(s.__fetchCleanups=[]),Wt();const i=e.refetchInterval;if(i){const o=typeof i=="number"?i:H(i);if(o>0){const a=setInterval(()=>{(e.refetchIntervalInBackground||typeof document>"u"||document.visibilityState==="visible")&&R(e,t,r,{force:!0})},o);s.__fetchCleanups.push(()=>clearInterval(a))}}if(e.refetchOnWindowFocus!==!1){const o=()=>{const a=lt(t,r),l=vt(t,r),n=Gt(e,a,l),h=V(n),g=wt(e.cache);(!h||h.stale||Date.now()-h.time>(g?.staleTime||0))&&R(e,t,r,{force:!0})};G.focus.add(o),s.__fetchCleanups.push(()=>G.focus.delete(o))}if(e.refetchOnReconnect!==!1){const o=()=>R(e,t,r,{force:!0});G.online.add(o),s.__fetchCleanups.push(()=>G.online.delete(o))}},Bt=(e,t,r)=>{if(!t.optimistic)return null;const s=e.__ref,i=t.as,o=e.state?.parse?e.state.parse():Y(e.state)?{...e.state}:e.state;s.__optimisticSnapshot=o;const a=u(t.optimistic)?t.optimistic(r,o,e):t.optimistic;return a!==void 0&&I(e,a,i),o},Ft=(e,t)=>{const r=e.__ref,s=r.__optimisticSnapshot;s!==void 0&&(I(e,s,t.as),delete r.__optimisticSnapshot)},Jt=async(e,t,r)=>{const s=r?.fetch;if(!s)return;const i=await Tt(s,r);if(!i)return;const o=t.__ref,{method:a,from:l,fields:n,transform:h,as:g,on:S,auth:et,headers:dt,baseUrl:rt,invalidates:T,optimistic:ht,onMutate:Q,onSuccess:q,onError:A,onSettled:$}=e;let w;if(n===!0||S==="submit")w=tt(t);else if(z(n)){const p=tt(t);w={};for(const L of n)w[L]=p[L]}else t.state?.parse?w=t.state.parse():Y(t.state)&&(w={...t.state});h&&(w=h(w,t,t.state)),u(Q)&&Q(w,t,t.state);const W=ht?Bt(t,e,w):null;o.__fetching=!0,k(t,{isFetching:!0,isLoading:!1,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),D(t,"onFetchStart"),P(e,t,"onFetchStart");const C=r?.analyze?.emitNetwork,x=C?typeof performance<"u"?performance.now():Date.now():0;C&&C({phase:"start",mode:"mutation",from:l,method:a});try{if(et!==!1&&i.auth!==!1&&i.getSession){const m=await i.getSession();if(et===!0&&!m){W!==void 0&&Ft(t,e);const O={message:"Not authenticated"};D(t,"onFetchError",O),P(e,t,"onFetchError",O);return}}const p=i[a];if(!u(p))return;const L={from:l,data:w,headers:dt,baseUrl:rt};e.params&&(L.params=kt(e.params,t,r));const K=lt(t,r);K&&(L.headers={...L.headers,"Accept-Language":K});const st=Ct(e),ot=await Pt(()=>p(L),st),{data:F,error:E}=ot||{};if(E){W!==void 0&&Ft(t,e),k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:E,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",E),u(A)&&A(E,w,t),u($)&&$(null,E,w,t),C&&C({phase:"error",mode:"mutation",from:l,method:a,error:E.message||String(E),durationMs:(typeof performance<"u"?performance.now():Date.now())-x});return}if(delete o.__optimisticSnapshot,F!==void 0){const m=g?{[g]:F}:F;t.state?.update&&t.state.update(m,{preventFetch:!0})}if(k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),D(t,"onFetchComplete",F),P(e,t,"onFetchComplete",F),u(q)&&q(F,w,t),u($)&&$(F,null,w,t),C&&C({phase:"success",mode:"mutation",ok:!0,from:l,method:a,durationMs:(typeof performance<"u"?performance.now():Date.now())-x}),T){const m=z(T)?T:[T];for(const O of m)if(O===!0||O==="*")for(const[U]of v)U.startsWith(l+":")&&Z(U);else Z(O)}}catch(p){W!==void 0&&Ft(t,e),k(t,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:p,status:"error",fetchStatus:"idle"}),D(t,"onFetchError",p),P(e,t,"onFetchError",p),u(A)&&A(p,w,t),u($)&&$(null,p,w,t),C&&C({phase:"error",mode:"mutation",from:l,method:a,error:p.message||String(p),durationMs:(typeof performance<"u"?performance.now():Date.now())-x})}finally{o.__fetching=!1}},$t=(e,t,r,s)=>{if(!e||!s?.fetch)return;const o=Et(e,t);if(!o)return;const a=z(o)?o.map(n=>Lt(Et(n,t),t)).filter(Boolean):[Lt(o,t)].filter(Boolean);for(const n of a){const h=n.method==="insert"||n.method==="update"||n.method==="upsert"||n.method==="delete",g=h?Jt:R;n.on==="create"?g(n,t,s):Promise.resolve().then(()=>{Kt({...n,__runner:g},t,s)}),!h&&n.on==="create"&&(n.refetchInterval||n.refetchOnWindowFocus!==!1||n.refetchOnReconnect!==!1)&&Yt(n,t,s)}const l=t.__ref;l.refetch=n=>{for(const h of a)R(h,t,s,{force:!0,...n})},l.fetchNextPage=()=>{const n=a[0];if(!n||!n.infinite)return;const h=l.__nextPageParam;if(h==null)return;const g={...n,cursor:h};R(g,t,s,{direction:"next",force:!0})},l.fetchPreviousPage=()=>{const n=a[0];if(!n||!n.infinite)return;const h=l.__prevPageParam;if(h==null)return;const g={...n,cursor:h};R(g,t,s,{direction:"previous",force:!0})}},re={invalidateQueries:e=>{if(!e){Z();return}if(B(e))for(const[t]of v)(t.startsWith(e)||t.includes(e))&&Z(t);else if(z(e)){const t=e.join(":");for(const[r]of v)r.includes(t)&&Z(r)}},removeQueries:e=>{if(!e){ct();return}if(B(e))for(const[t]of v)(t.startsWith(e)||t.includes(e))&&ct(t)},getQueryData:e=>V(e)?.data??void 0,setQueryData:(e,t)=>{const r=V(e),s=u(t)?t(r?.data):t;X(e,s,null)},prefetchQuery:async(e,t)=>{const r=t?.fetch;if(!r)return;const s=await Tt(r,t);if(!s)return;const i=e.cache?.key||`${e.from}:${e.method||"select"}:${JSON.stringify(e.params||"")}`,o=s[e.method||"select"];if(!u(o))return;const a=await o({from:e.from,params:e.params,limit:e.limit,offset:e.offset,order:e.order,single:e.single});if(a?.data!==void 0&&!a?.error){const l=X(i,a.data,null);l.gcTime=wt(e.cache)?.gcTime||3e5}return a},getCache:()=>v,clear:()=>ct(),dropNonLang:e=>{if(!e)return;const t=`:${e}`;for(const[r]of v)r.match(/:([a-z]{2,3})$/i)&&(r.endsWith(t)||ct(r))}},se={name:"fetch",create(e){const t=e.fetch;t&&(e.parent||j.clear(),$t(t,e,e.state,e.context))}};var oe=$t;export{te as createAdapter,oe as default,$t as executeFetch,se as fetchPlugin,mt as initAdapterAuth,H as parseDuration,re as queryClient,Zt as registerAdapter,jt as resolveDb};
1
+ import{isArray as Q,isFunction as l,isObject as V,isString as H,exec as Pt}from"@symbo.ls/utils";const zt=["select","rpc","insert","update","upsert","delete","subscribe"],jt={rest:()=>import("./adapters/rest.js"),local:()=>import("./adapters/local.js")},ut=Symbol.for("@symbo.ls/fetch:CUSTOM_ADAPTERS"),X=(()=>{if(typeof globalThis<"u"&&globalThis[ut])return globalThis[ut];const t={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,ut,{value:t,writable:!1,configurable:!1,enumerable:!1}),globalThis[ut]}catch{}return t})(),lt=Symbol.for("@symbo.ls/fetch:PENDING_ADAPTERS"),bt=(()=>{if(typeof globalThis<"u"&&globalThis[lt])return globalThis[lt];const t={};if(typeof globalThis<"u")try{return Object.defineProperty(globalThis,lt,{value:t,writable:!1,configurable:!1,enumerable:!1}),globalThis[lt]}catch{}return t})(),Bt=5e3,Gt=t=>new Promise(e=>{if(X[t])return e(X[t]);const s=bt[t]||=[];let r=!1;const o=()=>{r||(r=!0,e(X[t]||null))};s.push(o),setTimeout(o,Bt)}),re=(t,e)=>{X[t]=e;const s=bt[t];if(s&&s.length){bt[t]=[];for(const r of s)r()}},ne=t=>{const e={};for(const s of zt)t[s]&&(e[s]=t[s]);return e.name=t.name||"custom",e},Qt=async t=>{if(!t)return null;if(typeof t.select=="function")return t;const{adapter:e,...s}=t,r=typeof e=="string"?e:typeof t=="string"?t:null;if(!r)return null;let o=X[r]||jt[r];if(!o&&(o=await Gt(r),!o))throw new Error(`Unknown db adapter: "${r}". Use registerAdapter() for adapters with optional deps.`);const n=await o();if(!n||typeof n.setup!="function")throw new Error(`Adapter "${r}" loader returned a module without a setup() function. Got keys: [${Object.keys(n||{}).join(", ")}]. Likely a bundler chunk-resolution issue.`);return n.setup(s)},Z=t=>{if(!t)return 0;if(typeof t=="number")return t;const e=t.match(/^(\d+)(ms|s|m|h)$/);if(!e)return 0;const s=parseInt(e[1]),r=e[2];return r==="ms"?s:r==="s"?s*1e3:r==="m"?s*6e4:r==="h"?s*36e5:0},T=new Map,U=new Map,W=new Map,Wt=(t,e,s)=>{if(t.cache?.key)return t.cache.key;const r=Kt(t.params),o=s?`${s}:`:"",n=`${t.from}:${t.method}:${o}${JSON.stringify(r||"")}`;return e?`${n}:${e}`:n},tt=t=>T.get(t)||null,et=(t,e,s)=>{const r=T.get(t),o={data:e,error:s,time:Date.now(),stale:!1};T.set(t,o);const n=U.get(t);if(n)for(const a of n)l(a)&&a(o);return o},st=t=>{if(t){const e=T.get(t);e&&(e.stale=!0);return}for(const[,e]of T)e.stale=!0},dt=t=>{if(t){T.delete(t);return}T.clear()},oe=(t,e)=>(U.has(t)||U.set(t,new Set),U.get(t).add(e),()=>{const s=U.get(t);s&&(s.delete(e),s.size===0&&U.delete(t))}),wt=t=>!t&&t!==!1?{staleTime:6e4,gcTime:3e5}:t===!1?null:t===!0?{staleTime:6e4,gcTime:3e5}:typeof t=="number"?{staleTime:t,gcTime:Math.max(t*5,3e5)}:H(t)?{staleTime:Z(t),gcTime:3e5}:{staleTime:Z(t.stale||t.staleTime)||6e4,gcTime:Z(t.gc||t.gcTime||t.expire)||3e5,key:t.key};let ht=null;const Yt=()=>{ht||(ht=setInterval(()=>{const t=Date.now();for(const[e,s]of T){const r=U.get(e);!(r&&r.size>0)&&t-s.time>(s.gcTime||3e5)&&T.delete(e)}},3e4),ht.unref&&ht.unref())};Yt();const At=3,Tt=t=>Math.min(1e3*2**t,3e4),Lt=t=>{const e=t.retry;return e===!1?{count:0}:e===!0||e===void 0?{count:At,delay:Tt}:typeof e=="number"?{count:e,delay:Tt}:{count:e.count??At,delay:l(e.delay)?e.delay:typeof e.delay=="number"?()=>e.delay:Tt}},Ot=async(t,e)=>{const{count:s,delay:r}=e;let o;for(let n=0;n<=s;n++)try{const a=await t();if(a?.error){if(o=a.error,n<s){const c=l(r)?r(n,o):r;await new Promise(i=>setTimeout(i,c));continue}return a}return a}catch(a){if(o=a,n<s){const c=l(r)?r(n,a):r;await new Promise(i=>setTimeout(i,c));continue}throw a}return{data:null,error:o}},Y={focus:new Set,online:new Set};let Rt=!1;const xt=()=>{if(Rt||typeof window>"u")return;Rt=!0;const t=()=>{for(const s of Y.focus)s()},e=()=>{for(const s of Y.online)s()};window.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&t()}),window.addEventListener("focus",t),window.addEventListener("online",e)},kt=(t,e)=>{const s=e.__ref;if(t===!0)return{from:s.__state||e.key,method:"select",query:!0,on:"create"};if(H(t))return{from:t,method:"select",query:!0,on:"create"};if(V(t)){const r={...t};return r.from=r.from||s.__state||e.key,r.method=r.method||"select",r.on=r.on||"create",r.query===void 0&&(r.query=!0),r}return null},Kt=t=>(!t||l(t),t),pt=(t,e)=>{const s=t?.state?.root||e?.state?.root;if(s?.lang)return s.lang},mt=(t,e)=>{const r=(t?.state?.root||e?.state?.root)?.__fetchScope;return r?String(r):void 0},$t=(t,e,s)=>{let r;if(!t)r=void 0;else if(l(t))r=t(e,e.state);else{r={};for(const o in t){const n=t[o];r[o]=l(n)?n(e,e.state):n}}return r},vt=async(t,e)=>{if(!t||t.__authInitialized||(t.__authInitialized=!0,!t.getSession))return;const s=(r,o)=>{const n=e.state?.root;n?.update&&n.update({auth:{user:r,session:o,loading:!1}})};try{const r=await t.getSession();s(r?.user||null,r)}catch(r){console.warn("[fetch] Failed to restore auth session:",r.message)}t.onAuthStateChange&&t.onAuthStateChange((r,o)=>{s(o?.user||null,o)})},Ft=async(t,e)=>{if(l(t.select))return t.auth!==!1&&await vt(t,e),t;if(t.__resolved)return t.auth!==!1&&await vt(t.__resolved,e),t.__resolved;if(t.__resolving)return t.__resolving;t.__resolving=Qt(t);const s=await t.__resolving;return delete t.__resolving,s?(s.auth=t.auth,s.url=t.url,s.key=t.key,t.__resolved=s,e.fetch=s,t.auth!==!1&&await vt(s,e),s):null},E=(t,e,...s)=>{const r=l(t[e])?t[e]:null;r&&r.call(t,...s,t,t.state,t.context)},A=(t,e,s,...r)=>{const o=t&&l(t[s])?t[s]:null;o&&o.call(e,...r,e,e.state,e.context)},rt=t=>{const e={},s=t.node;if(!s)return e;if(s.tagName==="FORM"){const o=new FormData(s);for(const[n,a]of o.entries())e[n]=a;return e}const r=s.querySelectorAll("input, textarea, select");for(let o=0;o<r.length;o++){const n=r[o],a=n.name||n.getAttribute("name");a&&(n.type==="checkbox"?e[a]=n.checked:n.type==="file"?e[a]=n.files:e[a]=n.value)}return e},Et=t=>t.responseType==="stream"||t.responseType==="response",Jt=["Blob","File","ArrayBuffer","ReadableStream","Response"],Dt=t=>t!==null&&typeof t=="object"&&(ArrayBuffer.isView(t)||Jt.includes(Object.prototype.toString.call(t).slice(8,-1))),q=(t,e,s,r={})=>{if(!s&&Dt(e))return;const o=s&&s.startsWith("~/"),n=o&&t.state?.root||t.state;if(n?.update)if(o){const a=s.slice(2);e&&typeof e=="object"&&!Array.isArray(e)&&!Dt(e)&&a in e?n.update(e,{preventFetch:!0,...r}):n.update({[a]:e},{preventFetch:!0,...r})}else{const a=s?{[s]:e}:e;n.update(a,{preventFetch:!0,...r})}},L=(t,e)=>{const s=t?.__ref;s&&(s.__fetchStatus=e,s.__fetching=e.isFetching,s.__fetchError=e.error)},N=async(t,e,s,r={})=>{const o=s?.fetch;if(!o||!e||!e.__ref)return;const n=e.__ref,a=mt(e,s);(!n.__fetchScopeOwner||n.__fetchScopeOwner.scope!==a)&&(n.__fetchScopeOwner={scope:a});const c=n.__fetchScopeOwner,i=()=>e.__ref===n&&n.__fetchScopeOwner===c&&mt(e,s)===a;if(t.enabled===!1||l(t.enabled)&&!t.enabled(e,e.state)||t.skip===!0||l(t.skip)&&t.skip(e,e.state))return;const h=await Ft(o,s);if(!h||!i())return;const{from:g,method:S,query:R,params:x,cache:nt,transform:D,single:z,auth:ot,fields:j,as:k,limit:I,offset:$,order:b,headers:K,baseUrl:C,responseType:B,page:p,cursor:P,getNextPageParam:J,getPreviousPageParam:it,infinite:at,placeholderData:v,initialData:F,select:m,keepPreviousData:M}=t;let G=H(m)?m:void 0;if(R&&l(e.getQuery)){const d=e.getQuery(h.name||"paths");d&&(G=d.select||d.length&&d.join(",")||G)}const ft=$t(x,e,s),ct=Et(t)?null:wt(nt),Nt=Lt(t),_t=pt(e,s),It=_t?`:${_t}`:"",Ut=a?`${a}:`:"",_=ct?nt?.key||`${g}:${S}:${Ut}${JSON.stringify(ft||"")}${at?":infinite":""}${p?":p"+JSON.stringify(p):""}${It}`:null;if(!n.__fetchInitialized&&_&&(n.__fetchInitialized=!0,F!==void 0)){const d=l(F)?F():F;et(_,d,null)}if((S==="select"||S==="rpc")&&_&&ct){const d=tt(_);if(d&&!d.error){const u=Date.now()-d.time,y=d.stale||u>(ct.staleTime||0);let f=d.data;if(l(m)&&(f=m(f,e,e.state)),D&&(f=D(f,e,e.state)),!i())return;if(q(e,f,k),!y){L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"});return}}else if(v!==void 0){const u=l(v)?v(e,e.state):v;u!==void 0&&q(e,u,k)}}if(_&&W.has(_)&&!r.force){const d=W.get(_);try{const u=await Promise.race([d,new Promise((y,f)=>setTimeout(()=>f("DEDUP_TIMEOUT"),15e3))]);if(!i())return;if(u?.data!==void 0){let y=u.data;if(l(m)&&(y=m(y,e,e.state)),D&&(y=D(y,e,e.state)),!i())return;q(e,y,k),E(e,"onFetchComplete",y),A(t,e,"onFetchComplete",y)}}catch{if(!i())return}return}const qt=!tt(_)?.data;L(e,{isFetching:!0,isLoading:qt,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),E(e,"onFetchStart"),A(t,e,"onFetchStart");const O=s?.analyze?.emitNetwork,yt=O?typeof performance<"u"?performance.now():Date.now():0;O&&O({phase:"start",mode:"query",from:g,method:S,cacheKey:_,lang:_t});const gt=Ot(async()=>{if(!i())return;if(ot!==!1&&h.auth!==!1&&h.getSession){const f=await h.getSession();if(!i())return;if(ot===!0&&!f){const w={message:"Not authenticated"};return L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:w,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",w),A(t,e,"onFetchError",w),{data:null,error:w}}}const d=h[S];if(!l(d))return{data:null,error:{message:`Method "${S}" not found on adapter`}};const u={from:g,select:G,params:ft,single:z,limit:I,offset:$,order:b,headers:K,baseUrl:C};B!==void 0&&(u.responseType=B);const y=pt(e,s);if(y&&(u.headers={...u.headers,"Accept-Language":y}),p!==void 0){if(V(p))p.offset!==void 0&&(u.offset=p.offset),p.limit!==void 0&&(u.limit=p.limit),p.cursor!==void 0&&(u.params={...u.params,cursor:p.cursor});else if(typeof p=="number"){const f=t.pageSize||I||20;u.offset=(p-1)*f,u.limit=f}}if(P!==void 0&&(u.params={...u.params,cursor:P}),S==="insert"||S==="update"||S==="upsert"){let f;if(j===!0||t.on==="submit")f=rt(e);else if(Q(j)){const w=rt(e);f={};for(const St of j)f[St]=w[St]}else e.state?.parse?f=e.state.parse():V(e.state)&&(f={...e.state});D&&(f=D(f,e,e.state)),u.data=f}if(S==="rpc"){let f=ft;if(t.on==="submit"){const w=rt(e);f=t.transformParams?t.transformParams(w,e,e.state):w}u.params=f}if(S==="subscribe"){const f=h.subscribe({from:g,params:ft,on:t.subscribeOn},(w,St,ee)=>{i()&&(q(e,w,k),E(e,"onFetchComplete",w),A(t,e,"onFetchComplete",w))});return i()?(n.__unsubscribe=f,{data:null,error:null,subscribed:!0}):(l(f)&&f(),{data:null,error:null,subscribed:!0})}return d(u)},Nt);_&&W.set(_,gt);try{const d=await gt;if(!i()||d?.subscribed)return;const{data:u,error:y}=d||{};if(y){_&&et(_,null,y),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:y,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",y),A(t,e,"onFetchError",y),O&&O({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:y.message||y,durationMs:(typeof performance<"u"?performance.now():Date.now())-yt});return}if(u!==void 0){if((S==="select"||S==="rpc")&&_){const w=et(_,u,null);w.gcTime=ct?.gcTime||3e5}let f=u;if(at&&Q(u)&&(n.__pages||(n.__pages=[]),r.direction==="previous"?n.__pages.unshift(u):n.__pages.push(u),f=n.__pages.flat(),J&&(n.__nextPageParam=J(u,n.__pages),n.__hasNextPage=n.__nextPageParam!=null),it&&(n.__prevPageParam=it(u,n.__pages),n.__hasPreviousPage=n.__prevPageParam!=null)),l(m)&&(f=m(f,e,e.state)),D&&(f=D(f,e,e.state)),!i())return;(!M||f!==void 0)&&q(e,f,k),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),E(e,"onFetchComplete",f),A(t,e,"onFetchComplete",f),O&&O({phase:"success",mode:"query",ok:!0,from:g,method:S,cacheKey:_,durationMs:(typeof performance<"u"?performance.now():Date.now())-yt})}}catch(d){if(!i())return;L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:d,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",d),A(t,e,"onFetchError",d),O&&O({phase:"error",mode:"query",from:g,method:S,cacheKey:_,error:d.message||String(d),durationMs:(typeof performance<"u"?performance.now():Date.now())-yt})}finally{_&&W.get(_)===gt&&W.delete(_)}},Vt=(t,e,s)=>{const r=t.on,o=e.__ref;o.__fetchListeners||(o.__fetchListeners=[]);const n=t.__runner||N;if(r==="submit"){const a=i=>{i.preventDefault(),n(t,e,s)},c=e.node;c&&(c.addEventListener("submit",a),o.__fetchListeners.push(()=>c.removeEventListener("submit",a)))}else if(r==="click"){const a=()=>n(t,e,s),c=e.node;c&&(c.addEventListener("click",a),o.__fetchListeners.push(()=>c.removeEventListener("click",a)))}else r==="stateChange"&&(o.__fetchOnStateChange=()=>n(t,e,s))},Ht=(t,e,s)=>{const r=e.__ref;r.__fetchCleanups||(r.__fetchCleanups=[]),xt();const o=t.refetchInterval;if(o){const i=typeof o=="number"?o:Z(o);if(i>0){const h=setInterval(()=>{(t.refetchIntervalInBackground||typeof document>"u"||document.visibilityState==="visible")&&N(t,e,s,{force:!0})},i);r.__fetchCleanups.push(()=>clearInterval(h))}}const n=Et(t),a=t.refetchOnWindowFocus===void 0?!n:t.refetchOnWindowFocus!==!1,c=t.refetchOnReconnect===void 0?!n:t.refetchOnReconnect!==!1;if(a){const i=()=>{const h=pt(e,s),g=mt(e,s),S=Wt(t,h,g),R=tt(S),x=wt(t.cache);(!R||R.stale||Date.now()-R.time>(x?.staleTime||0))&&N(t,e,s,{force:!0})};Y.focus.add(i),r.__fetchCleanups.push(()=>Y.focus.delete(i))}if(c){const i=()=>N(t,e,s,{force:!0});Y.online.add(i),r.__fetchCleanups.push(()=>Y.online.delete(i))}},Xt=(t,e,s)=>{if(!e.optimistic)return null;const r=t.__ref,o=e.as,n=t.state?.parse?t.state.parse():V(t.state)?{...t.state}:t.state;r.__optimisticSnapshot=n;const a=l(e.optimistic)?e.optimistic(s,n,t):e.optimistic;return a!==void 0&&q(t,a,o),n},Ct=(t,e)=>{const s=t.__ref,r=s.__optimisticSnapshot;r!==void 0&&(q(t,r,e.as),delete s.__optimisticSnapshot)},Zt=async(t,e,s)=>{const r=s?.fetch;if(!r)return;const o=await Ft(r,s);if(!o)return;const n=e.__ref,{method:a,from:c,fields:i,transform:h,as:g,on:S,auth:R,headers:x,baseUrl:nt,responseType:D,invalidates:z,optimistic:ot,onMutate:j,onSuccess:k,onError:I,onSettled:$}=t;let b;if(i===!0||S==="submit")b=rt(e);else if(Q(i)){const p=rt(e);b={};for(const P of i)b[P]=p[P]}else e.state?.parse?b=e.state.parse():V(e.state)&&(b={...e.state});h&&(b=h(b,e,e.state)),l(j)&&j(b,e,e.state);const K=ot?Xt(e,t,b):null;n.__fetching=!0,L(e,{isFetching:!0,isLoading:!1,isStale:!1,isSuccess:!1,error:null,status:"pending",fetchStatus:"fetching"}),E(e,"onFetchStart"),A(t,e,"onFetchStart");const C=s?.analyze?.emitNetwork,B=C?typeof performance<"u"?performance.now():Date.now():0;C&&C({phase:"start",mode:"mutation",from:c,method:a});try{if(R!==!1&&o.auth!==!1&&o.getSession){const m=await o.getSession();if(R===!0&&!m){K!==void 0&&Ct(e,t);const M={message:"Not authenticated"};E(e,"onFetchError",M),A(t,e,"onFetchError",M);return}}const p=o[a];if(!l(p))return;const P={from:c,data:b,headers:x,baseUrl:nt};D!==void 0&&(P.responseType=D),t.params&&(P.params=$t(t.params,e,s));const J=pt(e,s);J&&(P.headers={...P.headers,"Accept-Language":J});const it=Lt(t),at=await Ot(()=>p(P),it),{data:v,error:F}=at||{};if(F){K!==void 0&&Ct(e,t),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:F,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",F),l(I)&&I(F,b,e),l($)&&$(null,F,b,e),C&&C({phase:"error",mode:"mutation",from:c,method:a,error:F.message||String(F),durationMs:(typeof performance<"u"?performance.now():Date.now())-B});return}if(delete n.__optimisticSnapshot,v!==void 0&&(g||!Dt(v))){const m=g?{[g]:v}:v;e.state?.update&&e.state.update(m,{preventFetch:!0})}if(L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!0,error:null,status:"success",fetchStatus:"idle"}),E(e,"onFetchComplete",v),A(t,e,"onFetchComplete",v),l(k)&&k(v,b,e),l($)&&$(v,null,b,e),C&&C({phase:"success",mode:"mutation",ok:!0,from:c,method:a,durationMs:(typeof performance<"u"?performance.now():Date.now())-B}),z){const m=Q(z)?z:[z];for(const M of m)if(M===!0||M==="*")for(const[G]of T)G.startsWith(c+":")&&st(G);else st(M)}}catch(p){K!==void 0&&Ct(e,t),L(e,{isFetching:!1,isLoading:!1,isStale:!1,isSuccess:!1,error:p,status:"error",fetchStatus:"idle"}),E(e,"onFetchError",p),A(t,e,"onFetchError",p),l(I)&&I(p,b,e),l($)&&$(null,p,b,e),C&&C({phase:"error",mode:"mutation",from:c,method:a,error:p.message||String(p),durationMs:(typeof performance<"u"?performance.now():Date.now())-B})}finally{n.__fetching=!1}},Mt=(t,e,s,r)=>{if(!t||!r?.fetch)return;const n=Pt(t,e);if(!n)return;const a=Q(n)?n.map(i=>kt(Pt(i,e),e)).filter(Boolean):[kt(n,e)].filter(Boolean);for(const i of a){const h=i.method==="insert"||i.method==="update"||i.method==="upsert"||i.method==="delete",g=h?Zt:N;i.on==="create"?g(i,e,r):Promise.resolve().then(()=>{Vt({...i,__runner:g},e,r)}),!h&&i.on==="create"&&(i.refetchInterval||i.refetchOnWindowFocus!==!1||i.refetchOnReconnect!==!1)&&Ht(i,e,r)}const c=e.__ref;c.refetch=i=>{for(const h of a)N(h,e,r,{force:!0,...i})},c.fetchNextPage=()=>{const i=a[0];if(!i||!i.infinite)return;const h=c.__nextPageParam;if(h==null)return;const g={...i,cursor:h};N(g,e,r,{direction:"next",force:!0})},c.fetchPreviousPage=()=>{const i=a[0];if(!i||!i.infinite)return;const h=c.__prevPageParam;if(h==null)return;const g={...i,cursor:h};N(g,e,r,{direction:"previous",force:!0})}},ie={invalidateQueries:t=>{if(!t){st();return}if(H(t))for(const[e]of T)(e.startsWith(t)||e.includes(t))&&st(e);else if(Q(t)){const e=t.join(":");for(const[s]of T)s.includes(e)&&st(s)}},removeQueries:t=>{if(!t){dt();return}if(H(t))for(const[e]of T)(e.startsWith(t)||e.includes(t))&&dt(e)},getQueryData:t=>tt(t)?.data??void 0,setQueryData:(t,e)=>{const s=tt(t),r=l(e)?e(s?.data):e;et(t,r,null)},prefetchQuery:async(t,e)=>{const s=e?.fetch;if(!s)return;const r=await Ft(s,e);if(!r)return;const o=t.cache?.key||`${t.from}:${t.method||"select"}:${JSON.stringify(t.params||"")}`,n=r[t.method||"select"];if(!l(n))return;const a={from:t.from,params:t.params,limit:t.limit,offset:t.offset,order:t.order,single:t.single,headers:t.headers,baseUrl:t.baseUrl};t.responseType!==void 0&&(a.responseType=t.responseType);const c=await n(a);if(c?.data!==void 0&&!c?.error&&!Et(t)){const i=et(o,c.data,null);i.gcTime=wt(t.cache)?.gcTime||3e5}return c},getCache:()=>T,clear:()=>dt(),dropNonLang:t=>{if(!t)return;const e=`:${t}`;for(const[s]of T)s.match(/:([a-z]{2,3})$/i)&&(s.endsWith(e)||dt(s))}},ae={name:"fetch",create(t){const e=t.fetch;e&&(t.parent||W.clear(),Mt(e,t,t.state,t.context))}};var fe=Mt;export{ne as createAdapter,fe as default,Mt as executeFetch,ae as fetchPlugin,vt as initAdapterAuth,Z as parseDuration,ie as queryClient,re as registerAdapter,Qt as resolveDb};
package/index.js CHANGED
@@ -521,9 +521,30 @@ const collectFormData = (element) => {
521
521
  return data
522
522
  }
523
523
 
524
+ // --- Response kinds (REST `responseType`) ---
525
+
526
+ // 'stream' and 'response' hand back a body that can be read ONCE. A cached or
527
+ // dedup-shared copy would reach its second reader already locked or used, so
528
+ // such queries skip the cache and the in-flight dedup, and they re-request on
529
+ // window focus / reconnect only when the config asks for it.
530
+ const isSingleUse = (config) => config.responseType === 'stream' || config.responseType === 'response'
531
+
532
+ // A response body the adapter returned as-is (Blob, ArrayBuffer, typed array,
533
+ // ReadableStream, Response). Such a value only lands in state under `as`:
534
+ // merging one into state would walk its prototype's enumerable members
535
+ // (`size`, `getReader`, …) into state keys. Detection reads the toStringTag,
536
+ // so values from another realm count too.
537
+ const BODY_VALUE_TAGS = ['Blob', 'File', 'ArrayBuffer', 'ReadableStream', 'Response']
538
+ const isBodyValue = (value) =>
539
+ value !== null && typeof value === 'object' &&
540
+ (ArrayBuffer.isView(value) || BODY_VALUE_TAGS.includes(Object.prototype.toString.call(value).slice(8, -1)))
541
+
524
542
  // --- State update helpers ---
525
543
 
526
544
  const updateElementState = (element, data, stateKey, options = {}) => {
545
+ // Nothing to merge — `transform` / `onFetchComplete` still receive it.
546
+ if (!stateKey && isBodyValue(data)) return
547
+
527
548
  const isRoot = stateKey && stateKey.startsWith('~/')
528
549
  const target = isRoot ? (element.state?.root || element.state) : element.state
529
550
  if (!target?.update) return
@@ -532,7 +553,7 @@ const updateElementState = (element, data, stateKey, options = {}) => {
532
553
  const key = stateKey.slice(2)
533
554
  // If transform returned an object containing the key itself, spread on root
534
555
  // e.g. transform returns { transactions: [...], totalSaved: 755 } for as: '~/transactions'
535
- if (data && typeof data === 'object' && !Array.isArray(data) && key in data) {
556
+ if (data && typeof data === 'object' && !Array.isArray(data) && !isBodyValue(data) && key in data) {
536
557
  target.update(data, { preventFetch: true, ...options })
537
558
  } else {
538
559
  target.update({ [key]: data }, { preventFetch: true, ...options })
@@ -598,7 +619,7 @@ const runFetch = async (config, element, context, opts = {}) => {
598
619
  const {
599
620
  from, method, query, params: rawParams, cache: cacheRaw, transform,
600
621
  single, auth, fields, as: stateKey, limit, offset, order,
601
- headers, baseUrl,
622
+ headers, baseUrl, responseType,
602
623
  // Pagination
603
624
  page, cursor, getNextPageParam, getPreviousPageParam, infinite,
604
625
  // TanStack-style options
@@ -613,7 +634,8 @@ const runFetch = async (config, element, context, opts = {}) => {
613
634
  }
614
635
 
615
636
  const params = resolveParams(rawParams, element, context)
616
- const cacheConfig = parseCacheConfig(cacheRaw)
637
+ // No cache key for a single-use body: no cache entry, no dedup sharing.
638
+ const cacheConfig = isSingleUse(config) ? null : parseCacheConfig(cacheRaw)
617
639
  const retryConfig = resolveRetryConfig(config)
618
640
  const lang = resolveLanguage(element, context)
619
641
 
@@ -720,6 +742,7 @@ const runFetch = async (config, element, context, opts = {}) => {
720
742
  if (!isFunction(fn)) return { data: null, error: { message: `Method "${method}" not found on adapter` } }
721
743
 
722
744
  const request = { from, select, params, single, limit, offset, order, headers, baseUrl }
745
+ if (responseType !== undefined) request.responseType = responseType
723
746
 
724
747
  // Inject language into request headers
725
748
  const lang = resolveLanguage(element, context)
@@ -936,8 +959,15 @@ const bindAutoRefetch = (config, element, context) => {
936
959
  }
937
960
  }
938
961
 
962
+ // A single-use body has no cache entry to go stale, so without an explicit
963
+ // opt-in every focus / reconnect would send the request again (re-asking a
964
+ // streamed answer, say). Other queries keep both on by default.
965
+ const singleUse = isSingleUse(config)
966
+ const onFocusEnabled = config.refetchOnWindowFocus === undefined ? !singleUse : config.refetchOnWindowFocus !== false
967
+ const onReconnectEnabled = config.refetchOnReconnect === undefined ? !singleUse : config.refetchOnReconnect !== false
968
+
939
969
  // refetchOnWindowFocus
940
- if (config.refetchOnWindowFocus !== false) {
970
+ if (onFocusEnabled) {
941
971
  const onFocus = () => {
942
972
  const lang = resolveLanguage(element, context)
943
973
  const scope = resolveScope(element, context)
@@ -953,7 +983,7 @@ const bindAutoRefetch = (config, element, context) => {
953
983
  }
954
984
 
955
985
  // refetchOnReconnect
956
- if (config.refetchOnReconnect !== false) {
986
+ if (onReconnectEnabled) {
957
987
  const onOnline = () => runFetch(config, element, context, { force: true })
958
988
  globalListeners.online.add(onOnline)
959
989
  ref.__fetchCleanups.push(() => globalListeners.online.delete(onOnline))
@@ -1001,7 +1031,7 @@ const runMutation = async (config, element, context) => {
1001
1031
  if (!adapter) return
1002
1032
 
1003
1033
  const ref = element.__ref
1004
- const { method, from, fields, transform, as: stateKey, on: trigger, auth, headers, baseUrl, invalidates, optimistic, onMutate, onSuccess, onError, onSettled } = config
1034
+ const { method, from, fields, transform, as: stateKey, on: trigger, auth, headers, baseUrl, responseType, invalidates, optimistic, onMutate, onSuccess, onError, onSettled } = config
1005
1035
 
1006
1036
  // Collect mutation data
1007
1037
  let mutationData
@@ -1050,6 +1080,7 @@ const runMutation = async (config, element, context) => {
1050
1080
  if (!isFunction(fn)) return
1051
1081
 
1052
1082
  const request = { from, data: mutationData, headers, baseUrl }
1083
+ if (responseType !== undefined) request.responseType = responseType
1053
1084
  if (config.params) request.params = resolveParams(config.params, element, context)
1054
1085
 
1055
1086
  // Inject language into mutation request headers
@@ -1078,7 +1109,8 @@ const runMutation = async (config, element, context) => {
1078
1109
 
1079
1110
  delete ref.__optimisticSnapshot
1080
1111
 
1081
- if (data !== undefined) {
1112
+ // A body value (Blob, stream, …) lands in state only under `as`.
1113
+ if (data !== undefined && (stateKey || !isBodyValue(data))) {
1082
1114
  const finalData = stateKey ? { [stateKey]: data } : data
1083
1115
  if (element.state?.update) element.state.update(finalData, { preventFetch: true })
1084
1116
  }
@@ -1243,16 +1275,20 @@ export const queryClient = {
1243
1275
  const fn = adapter[config.method || 'select']
1244
1276
  if (!isFunction(fn)) return
1245
1277
 
1246
- const result = await fn({
1278
+ const request = {
1247
1279
  from: config.from,
1248
1280
  params: config.params,
1249
1281
  limit: config.limit,
1250
1282
  offset: config.offset,
1251
1283
  order: config.order,
1252
- single: config.single
1253
- })
1284
+ single: config.single,
1285
+ headers: config.headers,
1286
+ baseUrl: config.baseUrl
1287
+ }
1288
+ if (config.responseType !== undefined) request.responseType = config.responseType
1289
+ const result = await fn(request)
1254
1290
 
1255
- if (result?.data !== undefined && !result?.error) {
1291
+ if (result?.data !== undefined && !result?.error && !isSingleUse(config)) {
1256
1292
  const entry = setCacheEntry(cacheKey, result.data, null)
1257
1293
  entry.gcTime = parseCacheConfig(config.cache)?.gcTime || 300000
1258
1294
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/fetch",
3
- "version": "3.14.659",
3
+ "version": "3.14.660",
4
4
  "license": "CC-BY-NC-4.0",
5
5
  "type": "module",
6
6
  "module": "./dist/esm/index.js",