@ventlio/tanstack-query 0.2.63 → 0.2.64

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 (42) hide show
  1. package/dist/config/bootstrapQueryRequest.d.ts +2 -2
  2. package/dist/config/bootstrapQueryRequest.js +1 -1
  3. package/dist/config/useEnvironmentVariables.js +2 -2
  4. package/dist/config/useReactNativeEnv.d.ts +1 -0
  5. package/dist/config/useReactNativeEnv.js +5 -16
  6. package/dist/config/useReactNativeEnv.js.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +228 -30
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/model/Model.d.ts +14 -0
  12. package/dist/model/Model.js +93 -0
  13. package/dist/model/Model.js.map +1 -0
  14. package/dist/model/index.d.ts +2 -0
  15. package/dist/model/model.interface.d.ts +7 -0
  16. package/dist/model/useQueryModel.d.ts +2 -2
  17. package/dist/model/useQueryModel.js +84 -2
  18. package/dist/model/useQueryModel.js.map +1 -1
  19. package/dist/queries/useDeleteRequest.js +1 -1
  20. package/dist/queries/usePatchRequest.js +0 -1
  21. package/dist/queries/usePatchRequest.js.map +1 -1
  22. package/dist/queries/usePostRequest.d.ts +2 -1
  23. package/dist/queries/usePostRequest.js +7 -2
  24. package/dist/queries/usePostRequest.js.map +1 -1
  25. package/dist/request/make-request.d.ts +1 -1
  26. package/dist/request/make-request.js +41 -7
  27. package/dist/request/make-request.js.map +1 -1
  28. package/dist/request/request.interface.d.ts +5 -0
  29. package/dist/types/index.d.ts +8 -3
  30. package/package.json +8 -2
  31. package/src/config/bootstrapQueryRequest.ts +3 -3
  32. package/src/config/useEnvironmentVariables.ts +2 -2
  33. package/src/config/useReactNativeEnv.ts +5 -20
  34. package/src/model/Model.ts +107 -0
  35. package/src/model/index.ts +2 -0
  36. package/src/model/model.interface.ts +10 -0
  37. package/src/model/useQueryModel.ts +123 -3
  38. package/src/queries/useDeleteRequest.ts +1 -1
  39. package/src/queries/usePostRequest.ts +8 -2
  40. package/src/request/make-request.ts +42 -6
  41. package/src/request/request.interface.ts +5 -0
  42. package/src/types/index.ts +9 -3
@@ -1,3 +1,3 @@
1
1
  import type { QueryClient } from '@tanstack/react-query';
2
- import type { BootstrapQueryRequest } from '../types';
3
- export declare const bootstrapQueryRequest: (queryClient: QueryClient, options?: BootstrapQueryRequest) => void;
2
+ import type { BootstrapConfig } from '../types';
3
+ export declare const bootstrapQueryRequest: (queryClient: QueryClient, options?: BootstrapConfig) => void;
@@ -4,7 +4,7 @@ const bootstrapQueryRequest = (queryClient, options) => {
4
4
  staleTime: Infinity,
5
5
  cacheTime: Infinity,
6
6
  });
7
- // set default query confg
7
+ // set default query config
8
8
  queryClient.setQueryData(['config'], {
9
9
  headers: {
10
10
  Authorization: ``,
@@ -2,8 +2,8 @@ import { useReactNativeEnv } from './useReactNativeEnv.js';
2
2
 
3
3
  const useEnvironmentVariables = () => {
4
4
  const { appTimeout, appUrl } = useReactNativeEnv();
5
- const url = process.env.REACT_APP_API_URL || process.env.NEXT_PUBLIC_API_URL || appUrl;
6
- const timeout = process.env.REACT_APP_API_TIMEOUT || process.env.NEXT_PUBLIC_API_TIMEOUT || appTimeout;
5
+ const url = process.env.REACT_APP_API_URL ?? process.env.NEXT_PUBLIC_API_URL ?? appUrl;
6
+ const timeout = process.env.REACT_APP_API_TIMEOUT ?? process.env.NEXT_PUBLIC_API_TIMEOUT ?? appTimeout;
7
7
  return {
8
8
  API_URL: url,
9
9
  TIMEOUT: Number(timeout),
@@ -1,4 +1,5 @@
1
1
  export declare const useReactNativeEnv: () => {
2
2
  appUrl: string | undefined;
3
3
  appTimeout: number | undefined;
4
+ isApp: boolean;
4
5
  };
@@ -1,23 +1,12 @@
1
1
  import { useQueryClient } from '@tanstack/react-query';
2
- import { useState, useEffect } from 'react';
3
2
 
4
3
  const useReactNativeEnv = () => {
5
4
  const queryClient = useQueryClient();
6
- const [appUrl, setAppUrl] = useState(undefined);
7
- const [appTimeout, setAppTimeout] = useState();
8
- useEffect(() => {
9
- const config = queryClient.getQueryData(['config']);
10
- const loadReactNativeEnvIfNeeded = async () => {
11
- if (config?.options?.context === 'app') {
12
- const API_URL = config.options.environments?.appBaseUrl;
13
- const API_TIMEOUT = config.options.environments?.appTimeout;
14
- setAppUrl(API_URL);
15
- setAppTimeout(API_TIMEOUT);
16
- }
17
- };
18
- loadReactNativeEnvIfNeeded();
19
- }, [queryClient]);
20
- return { appUrl, appTimeout };
5
+ const config = queryClient.getQueryData(['config']);
6
+ const appUrl = config?.options?.environments?.appBaseUrl;
7
+ const appTimeout = config?.options?.environments?.appTimeout;
8
+ const isApp = config?.options?.context === 'app';
9
+ return { appUrl, appTimeout, isApp };
21
10
  };
22
11
 
23
12
  export { useReactNativeEnv };
@@ -1 +1 @@
1
- {"version":3,"file":"useReactNativeEnv.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useReactNativeEnv.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export { useQueryHeaders } from './config/useQueryHeaders.js';
5
5
  export { useReactNativeEnv } from './config/useReactNativeEnv.js';
6
6
  export { scrollToTop } from './helpers/scrollToTop.js';
7
7
  export { getDateInFuture } from './helpers/timeFuncs.js';
8
+ export { QueryModel } from './model/Model.js';
8
9
  export { useKeyTrackerModel } from './model/useKeyTrackerModel.js';
9
10
  export { useQueryModel } from './model/useQueryModel.js';
10
11
  export { useRefetchQuery } from './model/useRefetchQuery.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,7 @@
1
1
  import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
2
- import { useState, useEffect, useMemo, startTransition } from 'react';
2
+ import result from 'lodash.result';
3
+ import set from 'lodash.set';
4
+ import { useState, useMemo, useEffect, startTransition } from 'react';
3
5
  import axios from 'axios';
4
6
 
5
7
  const bootstrapQueryRequest = (queryClient, options) => {
@@ -8,7 +10,7 @@ const bootstrapQueryRequest = (queryClient, options) => {
8
10
  staleTime: Infinity,
9
11
  cacheTime: Infinity,
10
12
  });
11
- // set default query confg
13
+ // set default query config
12
14
  queryClient.setQueryData(['config'], {
13
15
  headers: {
14
16
  Authorization: ``,
@@ -19,27 +21,17 @@ const bootstrapQueryRequest = (queryClient, options) => {
19
21
 
20
22
  const useReactNativeEnv = () => {
21
23
  const queryClient = useQueryClient();
22
- const [appUrl, setAppUrl] = useState(undefined);
23
- const [appTimeout, setAppTimeout] = useState();
24
- useEffect(() => {
25
- const config = queryClient.getQueryData(['config']);
26
- const loadReactNativeEnvIfNeeded = async () => {
27
- if (config?.options?.context === 'app') {
28
- const API_URL = config.options.environments?.appBaseUrl;
29
- const API_TIMEOUT = config.options.environments?.appTimeout;
30
- setAppUrl(API_URL);
31
- setAppTimeout(API_TIMEOUT);
32
- }
33
- };
34
- loadReactNativeEnvIfNeeded();
35
- }, [queryClient]);
36
- return { appUrl, appTimeout };
24
+ const config = queryClient.getQueryData(['config']);
25
+ const appUrl = config?.options?.environments?.appBaseUrl;
26
+ const appTimeout = config?.options?.environments?.appTimeout;
27
+ const isApp = config?.options?.context === 'app';
28
+ return { appUrl, appTimeout, isApp };
37
29
  };
38
30
 
39
31
  const useEnvironmentVariables = () => {
40
32
  const { appTimeout, appUrl } = useReactNativeEnv();
41
- const url = process.env.REACT_APP_API_URL || process.env.NEXT_PUBLIC_API_URL || appUrl;
42
- const timeout = process.env.REACT_APP_API_TIMEOUT || process.env.NEXT_PUBLIC_API_TIMEOUT || appTimeout;
33
+ const url = process.env.REACT_APP_API_URL ?? process.env.NEXT_PUBLIC_API_URL ?? appUrl;
34
+ const timeout = process.env.REACT_APP_API_TIMEOUT ?? process.env.NEXT_PUBLIC_API_TIMEOUT ?? appTimeout;
43
35
  return {
44
36
  API_URL: url,
45
37
  TIMEOUT: Number(timeout),
@@ -91,6 +83,94 @@ const useQueryHeaders = () => {
91
83
  return { setQueryHeaders, getHeaders };
92
84
  };
93
85
 
86
+ class QueryModel {
87
+ queryKey;
88
+ queryClient;
89
+ exact;
90
+ constructor(queryKey, queryClient, exact = true) {
91
+ this.queryKey = queryKey;
92
+ this.queryClient = queryClient;
93
+ this.exact = exact;
94
+ }
95
+ findAll(path) {
96
+ const data = this.queryClient.getQueryData(this.queryKey, { exact: this.exact });
97
+ if (!data) {
98
+ return [];
99
+ }
100
+ if (!path) {
101
+ return Array.isArray(data) ? data : [data];
102
+ }
103
+ return result(data, path, []);
104
+ }
105
+ findMany(selector, path) {
106
+ const data = this.findAll(path) ?? [];
107
+ return data.filter(selector);
108
+ }
109
+ find(id, path) {
110
+ const modelConfig = this.getModelConfig();
111
+ if (!modelConfig?.idColumn) {
112
+ return undefined;
113
+ }
114
+ const data = this.findAll(path) ?? [];
115
+ return data.find((record) => record[modelConfig.idColumn] === id);
116
+ }
117
+ update(id, data, path) {
118
+ const oldData = this.findAll(path) ?? [];
119
+ const modelConfig = this.getModelConfig();
120
+ if (!modelConfig?.idColumn) {
121
+ return undefined;
122
+ }
123
+ const idColumn = modelConfig.idColumn;
124
+ let updatedRecord = undefined;
125
+ const newData = oldData.map((record) => {
126
+ let dataRecord = record;
127
+ if (dataRecord[idColumn] === id) {
128
+ dataRecord = { ...dataRecord, ...data };
129
+ updatedRecord = dataRecord;
130
+ }
131
+ return dataRecord;
132
+ });
133
+ if (!path) {
134
+ this.queryClient.setQueryData(this.queryKey, newData);
135
+ }
136
+ else {
137
+ const queryData = this.queryClient.getQueryData(this.queryKey, { exact: this.exact }) ?? {};
138
+ this.queryClient.setQueryData(this.queryKey, set(queryData, path, newData));
139
+ }
140
+ return updatedRecord;
141
+ }
142
+ remove(id, path) {
143
+ const oldData = this.findAll(path) ?? [];
144
+ const modelConfig = this.getModelConfig();
145
+ if (!modelConfig?.idColumn) {
146
+ return false;
147
+ }
148
+ const idColumn = modelConfig.idColumn;
149
+ let updated = false;
150
+ const newData = oldData.filter((record) => {
151
+ const dataRecord = record;
152
+ if (dataRecord[idColumn] === id) {
153
+ updated = true;
154
+ return false;
155
+ }
156
+ return true;
157
+ });
158
+ if (!path) {
159
+ this.queryClient.setQueryData(this.queryKey, newData);
160
+ }
161
+ else {
162
+ const queryData = this.queryClient.getQueryData(this.queryKey, { exact: this.exact }) ?? {};
163
+ this.queryClient.setQueryData(this.queryKey, set(queryData, path, newData));
164
+ }
165
+ return updated;
166
+ }
167
+ getModelConfig() {
168
+ const { options } = this.queryClient.getQueryData(['config']) ?? {};
169
+ const { modelConfig } = options ?? {};
170
+ return modelConfig;
171
+ }
172
+ }
173
+
94
174
  const useKeyTrackerModel = (keyTracker) => {
95
175
  const queryClient = useQueryClient();
96
176
  const getQueryKey = (innerKeyTracker) => {
@@ -107,9 +187,88 @@ const useKeyTrackerModel = (keyTracker) => {
107
187
  return { refetchQuery, getQueryKey };
108
188
  };
109
189
 
110
- const useQueryModel = (queryKey, filters) => {
190
+ const useQueryModel = (keyTracker, exact = true) => {
111
191
  const queryClient = useQueryClient();
112
- return queryClient.getQueryData(queryKey, filters);
192
+ const { getQueryKey } = useKeyTrackerModel(keyTracker);
193
+ const queryKey = getQueryKey();
194
+ const findAll = (path) => {
195
+ const data = queryClient.getQueryData(queryKey, { exact });
196
+ if (!data) {
197
+ return [];
198
+ }
199
+ if (!path) {
200
+ return Array.isArray(data) ? data : [data];
201
+ }
202
+ return result(data, path, []);
203
+ };
204
+ const findMany = (selector, path) => {
205
+ const data = findAll(path) ?? [];
206
+ return data.filter(selector);
207
+ };
208
+ const find = (id, path) => {
209
+ const modelConfig = getModelConfig();
210
+ if (!modelConfig?.idColumn) {
211
+ return undefined;
212
+ }
213
+ const data = findAll(path) ?? [];
214
+ return data.find((record) => record[modelConfig.idColumn] === id);
215
+ };
216
+ const getModelConfig = () => {
217
+ const { options } = queryClient.getQueryData(['config']) ?? {};
218
+ const { modelConfig } = options ?? {};
219
+ return modelConfig;
220
+ };
221
+ const update = (id, data, path) => {
222
+ const oldData = findAll(path) ?? [];
223
+ const modelConfig = getModelConfig();
224
+ if (!modelConfig?.idColumn) {
225
+ return undefined;
226
+ }
227
+ const idColumn = modelConfig.idColumn;
228
+ let updatedRecord = undefined;
229
+ const newData = oldData.map((record) => {
230
+ let dataRecord = record;
231
+ if (dataRecord[idColumn] === id) {
232
+ dataRecord = { ...dataRecord, ...data };
233
+ updatedRecord = dataRecord;
234
+ }
235
+ return dataRecord;
236
+ });
237
+ if (!path) {
238
+ queryClient.setQueryData(queryKey, newData);
239
+ }
240
+ else {
241
+ const queryData = queryClient.getQueryData(queryKey, { exact }) ?? {};
242
+ queryClient.setQueryData(queryKey, set(queryData, path, newData));
243
+ }
244
+ return updatedRecord;
245
+ };
246
+ const remove = (id, path) => {
247
+ const oldData = findAll(path) ?? [];
248
+ const modelConfig = getModelConfig();
249
+ if (!modelConfig?.idColumn) {
250
+ return false;
251
+ }
252
+ const idColumn = modelConfig.idColumn;
253
+ let updated = false;
254
+ const newData = oldData.filter((record) => {
255
+ const dataRecord = record;
256
+ if (dataRecord[idColumn] === id) {
257
+ updated = true;
258
+ return false;
259
+ }
260
+ return true;
261
+ });
262
+ if (!path) {
263
+ queryClient.setQueryData(queryKey, newData);
264
+ }
265
+ else {
266
+ const queryData = queryClient.getQueryData(queryKey, { exact }) ?? {};
267
+ queryClient.setQueryData(queryKey, set(queryData, path, newData));
268
+ }
269
+ return updated;
270
+ };
271
+ return { find, findAll, findMany, remove, update };
113
272
  };
114
273
 
115
274
  const useRefetchQuery = async (queryKey) => {
@@ -209,20 +368,41 @@ const successTransformer = (data) => {
209
368
  };
210
369
  };
211
370
 
212
- async function makeRequest({ body, method = HttpMethod.GET, path, isFormData, headers = {}, baseURL, timeout, }) {
371
+ async function makeRequest({ body, method = HttpMethod.GET, path, isFormData, headers = {}, baseURL, timeout, appFileConfig, }) {
372
+ // check if file is included in mobile app environment and extract all file input to avoid
373
+ // it being formatted to object using axios formData builder
374
+ const isApp = appFileConfig?.isApp;
375
+ const appFiles = isApp ? getAppFiles(body, appFileConfig.fileSelectors) : {};
213
376
  // configure body
214
- body = isFormData ? buildFormData(body) : body;
215
- // configure request header
377
+ body = (isFormData ? axios.toFormData(body) : body);
378
+ // configure request header1
216
379
  if (!isFormData) {
217
380
  headers['Content-Type'] = ContentType.APPLICATION_JSON;
218
381
  }
219
382
  else {
220
- delete headers['Content-Type'];
383
+ if (isApp) {
384
+ headers['Content-Type'] = ContentType.MULTIPART_FORM_DATA;
385
+ // add the app files
386
+ for (const fileKey in appFiles) {
387
+ const currentFile = appFiles[fileKey];
388
+ if (Array.isArray(currentFile)) {
389
+ for (const innerFile of currentFile) {
390
+ body.append(fileKey, innerFile);
391
+ }
392
+ }
393
+ else {
394
+ body.append(fileKey, currentFile);
395
+ }
396
+ }
397
+ }
398
+ else {
399
+ delete headers['Content-Type'];
400
+ }
221
401
  }
222
402
  try {
223
- const axios = axiosInstance({ baseURL, headers, timeout });
403
+ const axiosRequest = axiosInstance({ baseURL, headers, timeout });
224
404
  // send request
225
- const resp = await axios({
405
+ const resp = await axiosRequest({
226
406
  url: path,
227
407
  method,
228
408
  data: body,
@@ -250,6 +430,19 @@ async function makeRequest({ body, method = HttpMethod.GET, path, isFormData, he
250
430
  ...errorData,
251
431
  });
252
432
  }
433
+ }
434
+ function getAppFiles(body, fileSelectors = []) {
435
+ const files = {};
436
+ if (body) {
437
+ if (fileSelectors.length > 0) {
438
+ //
439
+ for (const fileKey of fileSelectors) {
440
+ files[fileKey] = body[fileKey];
441
+ delete body[fileKey];
442
+ }
443
+ }
444
+ }
445
+ return files;
253
446
  }
254
447
 
255
448
  const useDeleteRequest = (deleteOptions) => {
@@ -287,7 +480,7 @@ const useDeleteRequest = (deleteOptions) => {
287
480
  internalDeleteOptions = internalDeleteOptions ?? {};
288
481
  internalDeleteOptions.enabled = true;
289
482
  await updatedPathAsync(link);
290
- await setOptionsAsync(deleteOptions);
483
+ await setOptionsAsync(internalDeleteOptions);
291
484
  return query.data;
292
485
  };
293
486
  return { destroy, ...query };
@@ -430,10 +623,11 @@ const usePatchRequest = ({ path, baseUrl, headers }) => {
430
623
  return { patch, ...mutation };
431
624
  };
432
625
 
433
- const usePostRequest = ({ path, isFormData = false, baseUrl, headers, }) => {
626
+ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelectors, }) => {
434
627
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
435
628
  const queryClient = useQueryClient();
436
629
  const { getHeaders } = useQueryHeaders();
630
+ const { isApp } = useReactNativeEnv();
437
631
  const sendRequest = async (res, rej, postData) => {
438
632
  // get request headers
439
633
  const globalHeaders = getHeaders();
@@ -446,6 +640,10 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, }) => {
446
640
  headers: { ...globalHeaders, ...headers },
447
641
  baseURL: baseUrl ?? API_URL,
448
642
  timeout: TIMEOUT,
643
+ appFileConfig: {
644
+ isApp,
645
+ fileSelectors,
646
+ },
449
647
  });
450
648
  if (postResponse.status) {
451
649
  // scroll to top after success
@@ -470,5 +668,5 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, }) => {
470
668
  return { post, ...mutation };
471
669
  };
472
670
 
473
- export { ContentType, HttpMethod, axiosInstance, bootstrapQueryRequest, buildFormData, errorTransformer, getDateInFuture, makeRequest, scrollToTop, successTransformer, useDeleteRequest, useEnvironmentVariables, useGetRequest, useKeyTrackerModel, usePatchRequest, usePostRequest, useQueryConfig, useQueryHeaders, useQueryModel, useReactNativeEnv, useRefetchQuery };
671
+ export { ContentType, HttpMethod, QueryModel, axiosInstance, bootstrapQueryRequest, buildFormData, errorTransformer, getDateInFuture, makeRequest, scrollToTop, successTransformer, useDeleteRequest, useEnvironmentVariables, useGetRequest, useKeyTrackerModel, usePatchRequest, usePostRequest, useQueryConfig, useQueryHeaders, useQueryModel, useReactNativeEnv, useRefetchQuery };
474
672
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,14 @@
1
+ import type { QueryClient } from '@tanstack/react-query';
2
+ import type { QueryModelBuilder } from './model.interface';
3
+ export declare class QueryModel<T> implements QueryModelBuilder<T> {
4
+ private readonly queryKey;
5
+ private readonly queryClient;
6
+ private readonly exact;
7
+ constructor(queryKey: any[], queryClient: QueryClient, exact?: boolean);
8
+ findAll(path?: string): T[] | undefined;
9
+ findMany(selector: (record: T) => boolean, path?: string): T[];
10
+ find(id: string | number, path?: string): T | undefined;
11
+ update(id: string | number, data: Partial<T>, path?: string): T | undefined;
12
+ remove(id: number | string, path?: string): boolean;
13
+ private getModelConfig;
14
+ }
@@ -0,0 +1,93 @@
1
+ import result from 'lodash.result';
2
+ import set from 'lodash.set';
3
+
4
+ class QueryModel {
5
+ queryKey;
6
+ queryClient;
7
+ exact;
8
+ constructor(queryKey, queryClient, exact = true) {
9
+ this.queryKey = queryKey;
10
+ this.queryClient = queryClient;
11
+ this.exact = exact;
12
+ }
13
+ findAll(path) {
14
+ const data = this.queryClient.getQueryData(this.queryKey, { exact: this.exact });
15
+ if (!data) {
16
+ return [];
17
+ }
18
+ if (!path) {
19
+ return Array.isArray(data) ? data : [data];
20
+ }
21
+ return result(data, path, []);
22
+ }
23
+ findMany(selector, path) {
24
+ const data = this.findAll(path) ?? [];
25
+ return data.filter(selector);
26
+ }
27
+ find(id, path) {
28
+ const modelConfig = this.getModelConfig();
29
+ if (!modelConfig?.idColumn) {
30
+ return undefined;
31
+ }
32
+ const data = this.findAll(path) ?? [];
33
+ return data.find((record) => record[modelConfig.idColumn] === id);
34
+ }
35
+ update(id, data, path) {
36
+ const oldData = this.findAll(path) ?? [];
37
+ const modelConfig = this.getModelConfig();
38
+ if (!modelConfig?.idColumn) {
39
+ return undefined;
40
+ }
41
+ const idColumn = modelConfig.idColumn;
42
+ let updatedRecord = undefined;
43
+ const newData = oldData.map((record) => {
44
+ let dataRecord = record;
45
+ if (dataRecord[idColumn] === id) {
46
+ dataRecord = { ...dataRecord, ...data };
47
+ updatedRecord = dataRecord;
48
+ }
49
+ return dataRecord;
50
+ });
51
+ if (!path) {
52
+ this.queryClient.setQueryData(this.queryKey, newData);
53
+ }
54
+ else {
55
+ const queryData = this.queryClient.getQueryData(this.queryKey, { exact: this.exact }) ?? {};
56
+ this.queryClient.setQueryData(this.queryKey, set(queryData, path, newData));
57
+ }
58
+ return updatedRecord;
59
+ }
60
+ remove(id, path) {
61
+ const oldData = this.findAll(path) ?? [];
62
+ const modelConfig = this.getModelConfig();
63
+ if (!modelConfig?.idColumn) {
64
+ return false;
65
+ }
66
+ const idColumn = modelConfig.idColumn;
67
+ let updated = false;
68
+ const newData = oldData.filter((record) => {
69
+ const dataRecord = record;
70
+ if (dataRecord[idColumn] === id) {
71
+ updated = true;
72
+ return false;
73
+ }
74
+ return true;
75
+ });
76
+ if (!path) {
77
+ this.queryClient.setQueryData(this.queryKey, newData);
78
+ }
79
+ else {
80
+ const queryData = this.queryClient.getQueryData(this.queryKey, { exact: this.exact }) ?? {};
81
+ this.queryClient.setQueryData(this.queryKey, set(queryData, path, newData));
82
+ }
83
+ return updated;
84
+ }
85
+ getModelConfig() {
86
+ const { options } = this.queryClient.getQueryData(['config']) ?? {};
87
+ const { modelConfig } = options ?? {};
88
+ return modelConfig;
89
+ }
90
+ }
91
+
92
+ export { QueryModel };
93
+ //# sourceMappingURL=Model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Model.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,3 +1,5 @@
1
+ export * from './Model';
2
+ export * from './model.interface';
1
3
  export * from './useKeyTrackerModel';
2
4
  export * from './useQueryModel';
3
5
  export * from './useRefetchQuery';
@@ -0,0 +1,7 @@
1
+ export interface QueryModelBuilder<T> {
2
+ findAll: (path?: string) => T[] | undefined;
3
+ findMany: (selector: (record: T) => boolean, path?: string) => T[];
4
+ find: (id: number | string, path?: string) => T | undefined;
5
+ update: (id: number | string, data: Partial<T>, path?: string) => T | undefined;
6
+ remove: (id: number, path?: string) => boolean;
7
+ }
@@ -1,2 +1,2 @@
1
- import type { QueryFilters } from '@tanstack/react-query';
2
- export declare const useQueryModel: (queryKey: any[], filters?: QueryFilters | undefined) => unknown;
1
+ import type { QueryModelBuilder } from './model.interface';
2
+ export declare const useQueryModel: <T>(keyTracker: string, exact?: boolean) => QueryModelBuilder<T>;
@@ -1,8 +1,90 @@
1
1
  import { useQueryClient } from '@tanstack/react-query';
2
+ import result from 'lodash.result';
3
+ import set from 'lodash.set';
4
+ import { useKeyTrackerModel } from './useKeyTrackerModel.js';
2
5
 
3
- const useQueryModel = (queryKey, filters) => {
6
+ const useQueryModel = (keyTracker, exact = true) => {
4
7
  const queryClient = useQueryClient();
5
- return queryClient.getQueryData(queryKey, filters);
8
+ const { getQueryKey } = useKeyTrackerModel(keyTracker);
9
+ const queryKey = getQueryKey();
10
+ const findAll = (path) => {
11
+ const data = queryClient.getQueryData(queryKey, { exact });
12
+ if (!data) {
13
+ return [];
14
+ }
15
+ if (!path) {
16
+ return Array.isArray(data) ? data : [data];
17
+ }
18
+ return result(data, path, []);
19
+ };
20
+ const findMany = (selector, path) => {
21
+ const data = findAll(path) ?? [];
22
+ return data.filter(selector);
23
+ };
24
+ const find = (id, path) => {
25
+ const modelConfig = getModelConfig();
26
+ if (!modelConfig?.idColumn) {
27
+ return undefined;
28
+ }
29
+ const data = findAll(path) ?? [];
30
+ return data.find((record) => record[modelConfig.idColumn] === id);
31
+ };
32
+ const getModelConfig = () => {
33
+ const { options } = queryClient.getQueryData(['config']) ?? {};
34
+ const { modelConfig } = options ?? {};
35
+ return modelConfig;
36
+ };
37
+ const update = (id, data, path) => {
38
+ const oldData = findAll(path) ?? [];
39
+ const modelConfig = getModelConfig();
40
+ if (!modelConfig?.idColumn) {
41
+ return undefined;
42
+ }
43
+ const idColumn = modelConfig.idColumn;
44
+ let updatedRecord = undefined;
45
+ const newData = oldData.map((record) => {
46
+ let dataRecord = record;
47
+ if (dataRecord[idColumn] === id) {
48
+ dataRecord = { ...dataRecord, ...data };
49
+ updatedRecord = dataRecord;
50
+ }
51
+ return dataRecord;
52
+ });
53
+ if (!path) {
54
+ queryClient.setQueryData(queryKey, newData);
55
+ }
56
+ else {
57
+ const queryData = queryClient.getQueryData(queryKey, { exact }) ?? {};
58
+ queryClient.setQueryData(queryKey, set(queryData, path, newData));
59
+ }
60
+ return updatedRecord;
61
+ };
62
+ const remove = (id, path) => {
63
+ const oldData = findAll(path) ?? [];
64
+ const modelConfig = getModelConfig();
65
+ if (!modelConfig?.idColumn) {
66
+ return false;
67
+ }
68
+ const idColumn = modelConfig.idColumn;
69
+ let updated = false;
70
+ const newData = oldData.filter((record) => {
71
+ const dataRecord = record;
72
+ if (dataRecord[idColumn] === id) {
73
+ updated = true;
74
+ return false;
75
+ }
76
+ return true;
77
+ });
78
+ if (!path) {
79
+ queryClient.setQueryData(queryKey, newData);
80
+ }
81
+ else {
82
+ const queryData = queryClient.getQueryData(queryKey, { exact }) ?? {};
83
+ queryClient.setQueryData(queryKey, set(queryData, path, newData));
84
+ }
85
+ return updated;
86
+ };
87
+ return { find, findAll, findMany, remove, update };
6
88
  };
7
89
 
8
90
  export { useQueryModel };
@@ -1 +1 @@
1
- {"version":3,"file":"useQueryModel.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
1
+ {"version":3,"file":"useQueryModel.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}