@symbo.ls/fetch 3.7.0 → 3.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +61 -0
  2. package/index.js +63 -14
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -682,6 +682,66 @@ const db = createAdapter({
682
682
  })
683
683
  ```
684
684
 
685
+ ## Language / i18n
686
+
687
+ Fetch automatically injects the current language into every request — both as a `lang` query parameter and as an `Accept-Language` header.
688
+
689
+ ### Setting the language
690
+
691
+ Set the language in root state:
692
+
693
+ ```js
694
+ state: { root: { lang: 'ka' } }
695
+ ```
696
+
697
+ Or use the polyglot plugin which manages `state.root.lang` automatically.
698
+
699
+ ### Per-request override
700
+
701
+ Override the language for a specific fetch by including `lang` in params:
702
+
703
+ ```js
704
+ {
705
+ fetch: {
706
+ from: 'articles',
707
+ params: { lang: 'de' } // overrides global language for this request
708
+ }
709
+ }
710
+ ```
711
+
712
+ ### How it works
713
+
714
+ 1. `lang` is added to `params` (sent as query parameter / RPC argument)
715
+ 2. `Accept-Language` header is set on the request
716
+ 3. If `params.lang` is already set explicitly, it is not overwritten
717
+
718
+ This follows the same pattern as XMA's `t()` function where `state.root.lang` is the source of truth for the current language.
719
+
720
+ ## Disabling fetch
721
+
722
+ Fetch is included by default in smbls. To disable it:
723
+
724
+ ```js
725
+ import { createDefine } from '@symbo.ls/smbls'
726
+
727
+ // Disable fetch, keep everything else
728
+ const options = {
729
+ define: createDefine({ fetch: false })
730
+ }
731
+ ```
732
+
733
+ ## domql plugin
734
+
735
+ Fetch can also be used as a domql plugin:
736
+
737
+ ```js
738
+ import { fetchPlugin } from '@symbo.ls/fetch'
739
+
740
+ context.plugins = [fetchPlugin]
741
+ ```
742
+
743
+ When used as a plugin, fetch hooks into the `create` lifecycle to auto-execute fetch configs defined on elements.
744
+
685
745
  ## All `fetch` options
686
746
 
687
747
  | Option | Type | Default | Description |
@@ -722,3 +782,4 @@ const db = createAdapter({
722
782
  | `order` | string/object/array | — | Sort order |
723
783
  | `headers` | object | — | Per-request headers (REST) |
724
784
  | `baseUrl` | string | — | Per-request base URL (REST) |
785
+ | `lang` | string | auto from context/state | Language override (via params) |
package/index.js CHANGED
@@ -257,13 +257,24 @@ const resolveParamsSync = (params) => {
257
257
  return params
258
258
  }
259
259
 
260
- const resolveParams = (params, element) => {
261
- if (!params) return undefined
262
- if (isFunction(params)) return params(element, element.state)
263
- const resolved = {}
264
- for (const key in params) {
265
- const val = params[key]
266
- resolved[key] = isFunction(val) ? val(element, element.state) : val
260
+ const resolveLanguage = (element, context) => {
261
+ const root = element?.state?.root || context?.state?.root
262
+ if (root?.lang) return root.lang
263
+ return undefined
264
+ }
265
+
266
+ const resolveParams = (params, element, context) => {
267
+ let resolved
268
+ if (!params) {
269
+ resolved = undefined
270
+ } else if (isFunction(params)) {
271
+ resolved = params(element, element.state)
272
+ } else {
273
+ resolved = {}
274
+ for (const key in params) {
275
+ const val = params[key]
276
+ resolved[key] = isFunction(val) ? val(element, element.state) : val
277
+ }
267
278
  }
268
279
  return resolved
269
280
  }
@@ -304,7 +315,7 @@ const resolveAdapter = async (db, context) => {
304
315
  db.__resolving = resolveDb(db)
305
316
  const resolved = await db.__resolving
306
317
  db.__resolved = resolved
307
- context.db = resolved
318
+ context.fetch = resolved
308
319
  delete db.__resolving
309
320
 
310
321
  // Auto-init auth when adapter supports it and db.auth is enabled
@@ -368,7 +379,7 @@ const setFetchStatus = (element, status) => {
368
379
  // --- Core fetch runner ---
369
380
 
370
381
  const runFetch = async (config, element, context, opts = {}) => {
371
- const db = context?.db
382
+ const db = context?.fetch
372
383
  if (!db) return
373
384
 
374
385
  // enabled check
@@ -396,7 +407,7 @@ const runFetch = async (config, element, context, opts = {}) => {
396
407
  if (q) select = q.select || (q.length && q.join(',')) || undefined
397
408
  }
398
409
 
399
- const params = resolveParams(rawParams, element)
410
+ const params = resolveParams(rawParams, element, context)
400
411
  const cacheConfig = parseCacheConfig(cacheRaw)
401
412
  const retryConfig = resolveRetryConfig(config)
402
413
 
@@ -484,6 +495,12 @@ const runFetch = async (config, element, context, opts = {}) => {
484
495
 
485
496
  const request = { from, select, params, single, limit, offset, order, headers, baseUrl }
486
497
 
498
+ // Inject language into request headers
499
+ const lang = resolveLanguage(element, context)
500
+ if (lang) {
501
+ request.headers = { ...request.headers, 'Accept-Language': lang }
502
+ }
503
+
487
504
  // Pagination support
488
505
  if (page !== undefined) {
489
506
  if (isObject(page)) {
@@ -722,7 +739,7 @@ const rollbackOptimistic = (element, config) => {
722
739
  // --- Mutation runner (insert/update/delete with optimistic + invalidation) ---
723
740
 
724
741
  const runMutation = async (config, element, context) => {
725
- const db = context?.db
742
+ const db = context?.fetch
726
743
  if (!db) return
727
744
 
728
745
  const adapter = await resolveAdapter(db, context)
@@ -772,7 +789,13 @@ const runMutation = async (config, element, context) => {
772
789
  if (!isFunction(fn)) return
773
790
 
774
791
  const request = { from, data: mutationData, headers, baseUrl }
775
- if (config.params) request.params = resolveParams(config.params, element)
792
+ if (config.params) request.params = resolveParams(config.params, element, context)
793
+
794
+ // Inject language into mutation request headers
795
+ const lang = resolveLanguage(element, context)
796
+ if (lang) {
797
+ request.headers = { ...request.headers, 'Accept-Language': lang }
798
+ }
776
799
 
777
800
  const retryConfig = resolveRetryConfig(config)
778
801
  const result = await withRetry(() => fn(request), retryConfig)
@@ -828,7 +851,7 @@ const runMutation = async (config, element, context) => {
828
851
 
829
852
  export const executeFetch = (param, element, state, context) => {
830
853
  if (!param) return
831
- const db = context?.db
854
+ const db = context?.fetch
832
855
  if (!db) return
833
856
 
834
857
  const fetchProp = exec(param, element)
@@ -933,7 +956,7 @@ export const queryClient = {
933
956
  },
934
957
 
935
958
  prefetchQuery: async (config, context) => {
936
- const db = context?.db
959
+ const db = context?.fetch
937
960
  if (!db) return
938
961
 
939
962
  const adapter = await resolveAdapter(db, context)
@@ -964,5 +987,31 @@ export const queryClient = {
964
987
  clear: () => removeCache()
965
988
  }
966
989
 
990
+ // --- Plugin interface ---
991
+
992
+ /**
993
+ * domql plugin for declarative data fetching.
994
+ *
995
+ * Usage:
996
+ * context.plugins = [fetchPlugin]
997
+ *
998
+ * Or with language:
999
+ * context.plugins = [fetchPlugin]
1000
+ * context.language = 'en'
1001
+ *
1002
+ * When used as a plugin, add `fetch` to `context.define` or
1003
+ * it is automatically registered via `defaultDefine.fetch`.
1004
+ */
1005
+ export const fetchPlugin = {
1006
+ name: 'fetch',
1007
+
1008
+ // Hook into element creation to auto-execute fetch configs
1009
+ create (element) {
1010
+ const fetchProp = element.fetch || element.props?.fetch
1011
+ if (!fetchProp) return
1012
+ executeFetch(fetchProp, element, element.state, element.context)
1013
+ }
1014
+ }
1015
+
967
1016
  export { parseDuration }
968
1017
  export default executeFetch
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/fetch",
3
- "version": "3.7.0",
3
+ "version": "3.7.3",
4
4
  "license": "CC-BY-NC-4.0",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -25,7 +25,7 @@
25
25
  "adapters"
26
26
  ],
27
27
  "dependencies": {
28
- "@domql/utils": "^3.7.0"
28
+ "@domql/utils": "^3.7.3"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@supabase/supabase-js": "^2.0.0"