mobx-tanstack-query-api 0.33.0 → 0.34.0

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/index.cjs CHANGED
@@ -7,6 +7,11 @@ const mobxTanstackQuery = require("mobx-tanstack-query");
7
7
  const mobx$1 = require("yummies/mobx");
8
8
  const qs = require("qs");
9
9
  class EndpointQuery extends mobxTanstackQuery.Query {
10
+ /**
11
+ * Creates `EndpointQuery` instance.
12
+ *
13
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-queries/#constructor)
14
+ */
10
15
  constructor(endpoint, inputQueryClient, queryOptionsInput) {
11
16
  const isQueryOptionsInputFn = typeof queryOptionsInput === "function";
12
17
  const unpackedQueryOptionsInput = isQueryOptionsInputFn ? queryOptionsInput() : queryOptionsInput;
@@ -156,12 +161,27 @@ class EndpointQuery extends mobxTanstackQuery.Query {
156
161
  this._observableData = _observableData;
157
162
  }
158
163
  _observableData;
164
+ /**
165
+ * Current endpoint params used by this query.
166
+ *
167
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-queries/#params)
168
+ */
159
169
  get params() {
160
170
  return this._observableData.params;
161
171
  }
172
+ /**
173
+ * Last raw HTTP response returned by endpoint.
174
+ *
175
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-queries/#response)
176
+ */
162
177
  get response() {
163
178
  return this._observableData.response;
164
179
  }
180
+ /**
181
+ * Updates query options and optionally params.
182
+ *
183
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-queries/#update)
184
+ */
165
185
  update(updateParams) {
166
186
  if ("params" in updateParams) {
167
187
  const { params, ...options } = updateParams;
@@ -189,12 +209,22 @@ class EndpointQuery extends mobxTanstackQuery.Query {
189
209
  return super.update(updateParams);
190
210
  }
191
211
  }
212
+ /**
213
+ * Refetches query when params are initialized.
214
+ *
215
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-queries/#refetch)
216
+ */
192
217
  refetch(options) {
193
218
  if (this.params) {
194
219
  return super.refetch(options);
195
220
  }
196
221
  return Promise.resolve(this.queryObserver.getCurrentResult());
197
222
  }
223
+ /**
224
+ * Sets params and starts query execution.
225
+ *
226
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-queries/#start)
227
+ */
198
228
  async start(params) {
199
229
  mobx.runInAction(() => {
200
230
  this._observableData.params = params;
@@ -324,6 +354,11 @@ class EndpointInfiniteQuery extends mobxTanstackQuery.InfiniteQuery {
324
354
  }
325
355
  }
326
356
  class EndpointMutation extends mobxTanstackQuery.Mutation {
357
+ /**
358
+ * Creates `EndpointMutation` instance.
359
+ *
360
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-mutations/#constructor)
361
+ */
327
362
  constructor(endpoint, inputQueryClient, {
328
363
  transform: transformResponse,
329
364
  invalidateEndpoints,
@@ -386,199 +421,67 @@ class EndpointMutation extends mobxTanstackQuery.Mutation {
386
421
  return await transformResponse?.(response) ?? response.data;
387
422
  }
388
423
  });
389
- this.endpoint = endpoint;
390
424
  }
391
425
  }
392
- const ContentType = {
393
- Json: "application/json",
394
- FormData: "multipart/form-data",
395
- UrlEncoded: "application/x-www-form-urlencoded",
396
- Text: "text/plain",
397
- Binary: "application/octet-stream"
398
- };
399
- const isHttpResponse = (response, status) => !!response && typeof response === "object" && response instanceof Response && "data" in response && (!status || response.status === status);
400
- const isHttpBadResponse = (response) => {
401
- return isHttpResponse(response) && (!response.ok || !!response.error);
402
- };
403
426
  const emptyStatusCodesSet = /* @__PURE__ */ new Set([204, 205, 304]);
404
- class HttpClient {
405
- config;
406
- fetch;
407
- meta;
408
- baseApiParams;
409
- badResponse;
410
- toQueryString;
411
- constructor(config) {
412
- this.config = config ?? {};
413
- this.badResponse = null;
414
- this.meta = config?.meta ?? null;
415
- this.fetch = config?.fetch ?? ((...fetchParams) => globalThis.fetch(...fetchParams));
416
- this.toQueryString = config?.toQueryString ?? ((query) => qs.stringify(query, config?.queryStringifyOptions));
417
- this.baseApiParams = {
418
- credentials: "same-origin",
419
- headers: {},
420
- redirect: "follow",
421
- referrerPolicy: "no-referrer"
422
- };
423
- this.updateConfig(this.config);
424
- mobx.observable.ref(this, "badResponse");
425
- mobx.observable.ref(this, "meta");
426
- mobx.action(this, "setMeta");
427
- mobx.action(this, "setBadResponse");
428
- mobx.makeObservable(this);
429
- }
430
- get baseUrl() {
431
- return this.config.baseUrl ?? "";
432
- }
433
- updateConfig(update) {
434
- Object.assign(this.config, update);
435
- if (update.baseApiParams) {
436
- Object.assign(this.baseApiParams, update.baseApiParams);
437
- }
438
- if (update.contentFormatters) {
439
- Object.assign(this.contentFormatters, update.contentFormatters);
440
- }
441
- if (update.fetch) {
442
- this.fetch = update.fetch;
443
- }
444
- }
445
- setMeta = (data) => {
446
- this.meta = data;
447
- };
448
- setBadResponse = (response) => {
449
- this.badResponse = response;
450
- };
451
- contentFormatters = {
452
- "application/json": (input) => input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input,
453
- "text/plain": (input) => input !== null && typeof input !== "string" ? JSON.stringify(input) : input,
454
- "multipart/form-data": (input) => Object.keys(input || {}).reduce((formData, key) => {
455
- const property = input[key];
456
- if (property instanceof Blob) {
457
- formData.append(key, property);
458
- } else if (typeof property === "object" && property !== null) {
459
- formData.append(key, JSON.stringify(property));
460
- } else {
461
- formData.append(key, `${property}`);
462
- }
463
- return formData;
464
- }, new FormData()),
465
- "application/x-www-form-urlencoded": (input) => this.toQueryString(input),
466
- "application/octet-stream": (input) => input
467
- };
468
- mergeRequestParams(params1, params2) {
469
- return {
470
- ...this.baseApiParams,
471
- ...params1,
472
- ...params2,
473
- headers: {
474
- ...this.baseApiParams.headers,
475
- ...params1.headers,
476
- ...params2?.headers
477
- }
478
- };
479
- }
480
- isEmptyResponseBody(response) {
481
- if (emptyStatusCodesSet.has(response.status)) {
427
+ class HttpResponse {
428
+ constructor(originalResponse, request) {
429
+ this.originalResponse = originalResponse;
430
+ this.request = request;
431
+ this.headers = originalResponse.headers;
432
+ this.ok = originalResponse.ok;
433
+ this.body = originalResponse.body;
434
+ this.redirected = originalResponse.redirected;
435
+ this.status = originalResponse.status;
436
+ this.statusText = originalResponse.statusText;
437
+ this.type = originalResponse.type;
438
+ this.url = originalResponse.url;
439
+ this.data = null;
440
+ this.error = null;
441
+ }
442
+ headers;
443
+ ok;
444
+ redirected;
445
+ statusText;
446
+ type;
447
+ url;
448
+ body;
449
+ data;
450
+ error;
451
+ status;
452
+ clone() {
453
+ return new HttpResponse(this.originalResponse.clone(), this.request);
454
+ }
455
+ isEmpty() {
456
+ if (emptyStatusCodesSet.has(this.status)) {
482
457
  return true;
483
458
  }
484
- const contentLength = response.headers.get("content-length");
459
+ const contentLength = this.headers.get("content-length");
485
460
  if (contentLength !== null && contentLength === "0") {
486
461
  return true;
487
462
  }
488
- if (response.body === null) {
463
+ if (this.body === null) {
489
464
  return true;
490
465
  }
491
466
  return false;
492
467
  }
493
- async createResponse(responseFormat = "json", raw, url, params) {
494
- const response = raw;
495
- response.request = { url, params };
496
- response.data = null;
497
- response.error = null;
498
- if (this.isEmptyResponseBody(response)) {
499
- return response;
500
- }
468
+ async resolveBody(responseFormat) {
501
469
  try {
502
- const formatted = await response[responseFormat]();
503
- if (response.ok) {
504
- response.data = formatted;
505
- } else {
506
- response.error = formatted;
507
- }
508
- } catch (error) {
509
- response.error = error;
510
- }
511
- if (!response.ok || response.error) {
512
- this.setBadResponse(response);
513
- }
514
- return response;
515
- }
516
- buildUrl = (params) => {
517
- const baseUrl = params.baseUrl ?? this.baseUrl ?? "";
518
- const path = params.path;
519
- const queryString = params.query && this.toQueryString(params.query);
520
- const query = queryString ? `?${queryString}` : "";
521
- if (this.config.buildUrl) {
522
- return this.config.buildUrl(params, { baseUrl, path, query }, this.meta);
523
- }
524
- const url = baseUrl + path + query;
525
- return url;
526
- };
527
- async request(fullParams, endpoint) {
528
- this.setBadResponse(null);
529
- const { body, contentType, format, ...params } = fullParams;
530
- let requestParams = this.mergeRequestParams(params);
531
- if (this.config.interceptor) {
532
- requestParams = await this.config.interceptor(requestParams, this.meta, endpoint) ?? requestParams;
533
- }
534
- const responseFormat = format || requestParams.format;
535
- const url = this.buildUrl(fullParams);
536
- let headers;
537
- if (requestParams.headers instanceof Headers) {
538
- headers = requestParams.headers;
539
- } else if (Array.isArray(requestParams.headers)) {
540
- headers = new Headers(requestParams.headers);
541
- } else {
542
- headers = new Headers(requestParams.headers);
543
- }
544
- let bodyToSend;
545
- if (contentType) {
546
- if (contentType !== ContentType.FormData && !headers.has("Content-Type")) {
547
- headers.set("Content-Type", contentType);
548
- }
549
- const payloadFormatter = this.contentFormatters[contentType];
550
- if (body == null) {
551
- bodyToSend = null;
552
- } else if (payloadFormatter) {
553
- bodyToSend = payloadFormatter(body);
470
+ const formatted = await this.originalResponse[responseFormat]();
471
+ if (this.ok) {
472
+ this.data = formatted;
554
473
  } else {
555
- bodyToSend = body;
474
+ this.error = formatted;
556
475
  }
557
- }
558
- const fetchUrl = url;
559
- const fetchParams = {
560
- ...requestParams,
561
- headers,
562
- body: bodyToSend
563
- };
564
- let response;
565
- try {
566
- response = await this.fetch(fetchUrl, fetchParams);
567
476
  } catch (error) {
568
- response = error;
569
- }
570
- const httpResponse = await this.createResponse(
571
- responseFormat,
572
- response,
573
- fetchUrl,
574
- fetchParams
575
- );
576
- if (!httpResponse.ok || httpResponse.error) {
577
- throw httpResponse;
477
+ this.error = error;
578
478
  }
579
- return httpResponse;
580
479
  }
581
480
  }
481
+ const isHttpResponse = (response, status) => typeof response === "object" && response instanceof HttpResponse && "data" in response && (!status || response.status === status);
482
+ const isHttpBadResponse = (response) => {
483
+ return isHttpResponse(response) && (!response.ok || !!response.error);
484
+ };
582
485
  class Endpoint {
583
486
  constructor(configuration, queryClient, httpClient) {
584
487
  this.configuration = configuration;
@@ -705,6 +608,11 @@ class Endpoint {
705
608
  }
706
609
  }
707
610
  class EndpointQueryClient extends mobxTanstackQuery.QueryClient {
611
+ /**
612
+ * Creates `EndpointQueryClient` instance.
613
+ *
614
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-query-client/#constructor)
615
+ */
708
616
  constructor(config) {
709
617
  super({
710
618
  ...config,
@@ -717,6 +625,11 @@ class EndpointQueryClient extends mobxTanstackQuery.QueryClient {
717
625
  }
718
626
  });
719
627
  }
628
+ /**
629
+ * Invalidates endpoint queries by endpoint metadata filters.
630
+ *
631
+ * [**Documentation**](https://js2me.github.io/mobx-tanstack-query-api/endpoint-query-client/#invalidateendpoints)
632
+ */
720
633
  invalidateEndpoints({
721
634
  group,
722
635
  namespace,
@@ -786,12 +699,173 @@ const applyStringFilter = (filter, value) => {
786
699
  }
787
700
  return values.includes(filter);
788
701
  };
702
+ const ContentType = {
703
+ Json: "application/json",
704
+ FormData: "multipart/form-data",
705
+ UrlEncoded: "application/x-www-form-urlencoded",
706
+ Text: "text/plain",
707
+ Binary: "application/octet-stream"
708
+ };
709
+ class HttpClient {
710
+ config;
711
+ fetch;
712
+ meta;
713
+ baseApiParams;
714
+ badResponse;
715
+ toQueryString;
716
+ constructor(config) {
717
+ this.config = config ?? {};
718
+ this.badResponse = null;
719
+ this.meta = config?.meta ?? null;
720
+ this.fetch = config?.fetch ?? ((...fetchParams) => globalThis.fetch(...fetchParams));
721
+ this.toQueryString = config?.toQueryString ?? ((query) => qs.stringify(query, config?.queryStringifyOptions));
722
+ this.baseApiParams = {
723
+ credentials: "same-origin",
724
+ headers: {},
725
+ redirect: "follow",
726
+ referrerPolicy: "no-referrer"
727
+ };
728
+ this.updateConfig(this.config);
729
+ mobx.observable.ref(this, "badResponse");
730
+ mobx.observable.ref(this, "meta");
731
+ mobx.action(this, "setMeta");
732
+ mobx.action(this, "setBadResponse");
733
+ mobx.makeObservable(this);
734
+ }
735
+ get baseUrl() {
736
+ return this.config.baseUrl ?? "";
737
+ }
738
+ updateConfig(update) {
739
+ Object.assign(this.config, update);
740
+ if (update.baseApiParams) {
741
+ Object.assign(this.baseApiParams, update.baseApiParams);
742
+ }
743
+ if (update.contentFormatters) {
744
+ Object.assign(this.contentFormatters, update.contentFormatters);
745
+ }
746
+ if (update.fetch) {
747
+ this.fetch = update.fetch;
748
+ }
749
+ }
750
+ setMeta = (data) => {
751
+ this.meta = data;
752
+ };
753
+ setBadResponse = (response) => {
754
+ this.badResponse = response;
755
+ };
756
+ contentFormatters = {
757
+ "application/json": (input) => input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input,
758
+ "text/plain": (input) => input !== null && typeof input !== "string" ? JSON.stringify(input) : input,
759
+ "multipart/form-data": (input) => Object.keys(input || {}).reduce((formData, key) => {
760
+ const property = input[key];
761
+ if (property instanceof Blob) {
762
+ formData.append(key, property);
763
+ } else if (typeof property === "object" && property !== null) {
764
+ formData.append(key, JSON.stringify(property));
765
+ } else {
766
+ formData.append(key, `${property}`);
767
+ }
768
+ return formData;
769
+ }, new FormData()),
770
+ "application/x-www-form-urlencoded": (input) => this.toQueryString(input),
771
+ "application/octet-stream": (input) => input
772
+ };
773
+ mergeRequestParams(params1, params2) {
774
+ return {
775
+ ...this.baseApiParams,
776
+ ...params1,
777
+ ...params2,
778
+ headers: {
779
+ ...this.baseApiParams.headers,
780
+ ...params1.headers,
781
+ ...params2?.headers
782
+ }
783
+ };
784
+ }
785
+ async createResponse(responseFormat = "json", raw, url, params) {
786
+ const response = new HttpResponse(raw, { url, params });
787
+ if (response.isEmpty()) {
788
+ return response;
789
+ }
790
+ await response.resolveBody(responseFormat);
791
+ if (!response.ok || response.error) {
792
+ this.setBadResponse(response);
793
+ }
794
+ return response;
795
+ }
796
+ buildUrl = (params) => {
797
+ const baseUrl = params.baseUrl ?? this.baseUrl ?? "";
798
+ const path = params.path;
799
+ const queryString = params.query && this.toQueryString(params.query);
800
+ const query = queryString ? `?${queryString}` : "";
801
+ if (this.config.buildUrl) {
802
+ return this.config.buildUrl(params, { baseUrl, path, query }, this.meta);
803
+ }
804
+ const url = baseUrl + path + query;
805
+ return url;
806
+ };
807
+ async request(fullParams, endpoint) {
808
+ this.setBadResponse(null);
809
+ const { body, contentType, format, ...params } = fullParams;
810
+ let requestParams = this.mergeRequestParams(params);
811
+ if (this.config.interceptor) {
812
+ requestParams = await this.config.interceptor(requestParams, this.meta, endpoint) ?? requestParams;
813
+ }
814
+ const responseFormat = format || requestParams.format;
815
+ const url = this.buildUrl(fullParams);
816
+ let headers;
817
+ if (requestParams.headers instanceof Headers) {
818
+ headers = requestParams.headers;
819
+ } else if (Array.isArray(requestParams.headers)) {
820
+ headers = new Headers(requestParams.headers);
821
+ } else {
822
+ headers = new Headers(requestParams.headers);
823
+ }
824
+ let bodyToSend;
825
+ if (contentType) {
826
+ if (contentType !== ContentType.FormData && !headers.has("Content-Type")) {
827
+ headers.set("Content-Type", contentType);
828
+ }
829
+ const payloadFormatter = this.contentFormatters[contentType];
830
+ if (body == null) {
831
+ bodyToSend = null;
832
+ } else if (payloadFormatter) {
833
+ bodyToSend = payloadFormatter(body);
834
+ } else {
835
+ bodyToSend = body;
836
+ }
837
+ }
838
+ const fetchUrl = url;
839
+ const fetchParams = {
840
+ ...requestParams,
841
+ headers,
842
+ body: bodyToSend
843
+ };
844
+ let response;
845
+ try {
846
+ response = await this.fetch(fetchUrl, fetchParams);
847
+ } catch (error) {
848
+ response = error;
849
+ }
850
+ const httpResponse = await this.createResponse(
851
+ responseFormat,
852
+ response,
853
+ fetchUrl,
854
+ fetchParams
855
+ );
856
+ if (!httpResponse.ok || httpResponse.error) {
857
+ throw httpResponse;
858
+ }
859
+ return httpResponse;
860
+ }
861
+ }
789
862
  exports.ContentType = ContentType;
790
863
  exports.Endpoint = Endpoint;
791
864
  exports.EndpointMutation = EndpointMutation;
792
865
  exports.EndpointQuery = EndpointQuery;
793
866
  exports.EndpointQueryClient = EndpointQueryClient;
794
867
  exports.HttpClient = HttpClient;
868
+ exports.HttpResponse = HttpResponse;
795
869
  exports.buildOptionsFromParams = buildOptionsFromParams;
796
870
  exports.emptyStatusCodesSet = emptyStatusCodesSet;
797
871
  exports.getParamsFromContext = getParamsFromContext;