@metamask-previews/react-data-query 0.0.0-preview-a0caca0c0 → 0.1.0-preview-afe010990

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/CHANGELOG.md CHANGED
@@ -7,4 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- [Unreleased]: https://github.com/MetaMask/core/
10
+ ### Added
11
+
12
+ - Allow passing additional configuration options to `createUIQueryClient` ([#8295](https://github.com/MetaMask/core/pull/8295))
13
+ - Move data service specific query configuration to hooks instead of `QueryClient` defaults ([#8296](https://github.com/MetaMask/core/pull/8296))
14
+
15
+ ## [0.1.0]
16
+
17
+ ### Added
18
+
19
+ - Initial release ([#8039](https://github.com/MetaMask/core/pull/8039), [#8292](https://github.com/MetaMask/core/pull/8292))
20
+
21
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/react-data-query@0.1.0...HEAD
22
+ [0.1.0]: https://github.com/MetaMask/core/releases/tag/@metamask/react-data-query@0.1.0
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createUIQueryClient = void 0;
4
+ const utils_1 = require("@metamask/utils");
5
+ const query_core_1 = require("@tanstack/query-core");
6
+ /**
7
+ * Create a QueryClient queries and subscribes to data services using the messenger.
8
+ *
9
+ * @param dataServices - A list of data services.
10
+ * @param messenger - A messenger adapter.
11
+ * @param config - Optional query client configuration options.
12
+ * @returns The QueryClient.
13
+ */
14
+ function createUIQueryClient(dataServices, messenger, config = {}) {
15
+ const subscriptions = new Map();
16
+ /**
17
+ * Parse a query key to detect a service name.
18
+ *
19
+ * @param queryKey - The query key.
20
+ * @returns The service name if it parsing succeeded, otherwise null.
21
+ */
22
+ function parseQueryKey(queryKey) {
23
+ const action = queryKey[0];
24
+ if (typeof action !== 'string') {
25
+ return null;
26
+ }
27
+ const service = action.split(':')[0];
28
+ if (!dataServices.includes(service)) {
29
+ return null;
30
+ }
31
+ return service;
32
+ }
33
+ const client = new query_core_1.QueryClient({
34
+ ...config,
35
+ defaultOptions: {
36
+ queries: {
37
+ ...config.defaultOptions?.queries,
38
+ queryFn: async (options) => {
39
+ const { queryKey } = options;
40
+ const action = queryKey[0];
41
+ (0, utils_1.assert)(typeof action === 'string' &&
42
+ dataServices.includes(action.split(':')?.[0]), "Queries must call actions on the messenger provided to createUIQueryClient, e.g. `queryKey: ['ExampleDataService:getAssets', ...]`.");
43
+ return await messenger.call(action, ...options.queryKey.slice(1), options.pageParam);
44
+ },
45
+ },
46
+ mutations: config.defaultOptions?.mutations,
47
+ },
48
+ });
49
+ const cache = client.getQueryCache();
50
+ cache.subscribe((event) => {
51
+ const { query } = event;
52
+ const hash = query.queryHash;
53
+ const hasSubscription = subscriptions.has(hash);
54
+ const observerCount = query.getObserversCount();
55
+ const service = parseQueryKey(query.queryKey);
56
+ if (!service) {
57
+ return;
58
+ }
59
+ if (!hasSubscription &&
60
+ event.type === 'observerAdded' &&
61
+ observerCount === 1) {
62
+ const cacheListener = (payload) => {
63
+ if (payload.type === 'removed') {
64
+ const currentQuery = cache.get(hash);
65
+ if (currentQuery) {
66
+ cache.remove(currentQuery);
67
+ }
68
+ }
69
+ else {
70
+ (0, query_core_1.hydrate)(client, payload.state);
71
+ }
72
+ };
73
+ subscriptions.set(hash, cacheListener);
74
+ messenger.subscribe(`${service}:cacheUpdated:${hash}`, cacheListener);
75
+ }
76
+ else if (event.type === 'observerRemoved' &&
77
+ observerCount === 0 &&
78
+ hasSubscription) {
79
+ const subscriptionListener = subscriptions.get(hash);
80
+ messenger.unsubscribe(`${service}:cacheUpdated:${hash}`, subscriptionListener);
81
+ subscriptions.delete(hash);
82
+ }
83
+ });
84
+ // Override invalidateQueries to ensure the data service is invalidated as well.
85
+ const originalInvalidate = client.invalidateQueries.bind(client);
86
+ // This function is defined in this way to have full support for all function overloads.
87
+ client.invalidateQueries = async (arg1, arg2, arg3) => {
88
+ const [filters, options] = (0, query_core_1.parseFilterArgs)(arg1, arg2, arg3);
89
+ const queries = client.getQueryCache().findAll(filters);
90
+ const services = [
91
+ ...new Set(queries.map((query) => parseQueryKey(query.queryKey))),
92
+ ];
93
+ await Promise.all(services.map(async (service) => {
94
+ if (!service) {
95
+ return null;
96
+ }
97
+ return messenger.call(`${service}:invalidateQueries`, filters, options);
98
+ }));
99
+ return originalInvalidate(filters, options);
100
+ };
101
+ return client;
102
+ }
103
+ exports.createUIQueryClient = createUIQueryClient;
104
+ //# sourceMappingURL=createUIQueryClient.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createUIQueryClient.cjs","sourceRoot":"","sources":["../src/createUIQueryClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { DataServiceGranularCacheUpdatedPayload } from '@metamask/base-data-service';\nimport { assert, Json } from '@metamask/utils';\nimport {\n hydrate,\n QueryClient,\n InvalidateQueryFilters,\n InvalidateOptions,\n OmitKeyof,\n parseFilterArgs,\n QueryKey,\n QueryClientConfig,\n} from '@tanstack/query-core';\n\ntype SubscriptionCallback = (\n payload: DataServiceGranularCacheUpdatedPayload,\n) => void;\n\ntype JsonSubscriptionCallback = (data: Json) => void;\n\n// TODO: Figure out if we can replace with a better Messenger type\ntype MessengerAdapter = {\n call: (method: string, ...params: Json[]) => Promise<Json | void>;\n subscribe: (method: string, callback: JsonSubscriptionCallback) => void;\n unsubscribe: (method: string, callback: JsonSubscriptionCallback) => void;\n};\n\n/**\n * Create a QueryClient queries and subscribes to data services using the messenger.\n *\n * @param dataServices - A list of data services.\n * @param messenger - A messenger adapter.\n * @param config - Optional query client configuration options.\n * @returns The QueryClient.\n */\nexport function createUIQueryClient(\n dataServices: string[],\n messenger: MessengerAdapter,\n config: QueryClientConfig = {},\n): QueryClient {\n const subscriptions = new Map<string, SubscriptionCallback>();\n\n /**\n * Parse a query key to detect a service name.\n *\n * @param queryKey - The query key.\n * @returns The service name if it parsing succeeded, otherwise null.\n */\n function parseQueryKey(queryKey: QueryKey): string | null {\n const action = queryKey[0];\n\n if (typeof action !== 'string') {\n return null;\n }\n\n const service = action.split(':')[0];\n\n if (!dataServices.includes(service)) {\n return null;\n }\n\n return service;\n }\n\n const client: QueryClient = new QueryClient({\n ...config,\n defaultOptions: {\n queries: {\n ...config.defaultOptions?.queries,\n queryFn: async (options): Promise<unknown> => {\n const { queryKey } = options;\n\n const action = queryKey[0];\n\n assert(\n typeof action === 'string' &&\n dataServices.includes(action.split(':')?.[0]),\n \"Queries must call actions on the messenger provided to createUIQueryClient, e.g. `queryKey: ['ExampleDataService:getAssets', ...]`.\",\n );\n\n return await messenger.call(\n action,\n ...(options.queryKey.slice(1) as Json[]),\n options.pageParam,\n );\n },\n },\n mutations: config.defaultOptions?.mutations,\n },\n });\n\n const cache = client.getQueryCache();\n\n cache.subscribe((event) => {\n const { query } = event;\n\n const hash = query.queryHash;\n const hasSubscription = subscriptions.has(hash);\n const observerCount = query.getObserversCount();\n\n const service = parseQueryKey(query.queryKey);\n\n if (!service) {\n return;\n }\n\n if (\n !hasSubscription &&\n event.type === 'observerAdded' &&\n observerCount === 1\n ) {\n const cacheListener = (\n payload: DataServiceGranularCacheUpdatedPayload,\n ): void => {\n if (payload.type === 'removed') {\n const currentQuery = cache.get(hash);\n\n if (currentQuery) {\n cache.remove(currentQuery);\n }\n } else {\n hydrate(client, payload.state);\n }\n };\n\n subscriptions.set(hash, cacheListener);\n messenger.subscribe(\n `${service}:cacheUpdated:${hash}`,\n cacheListener as JsonSubscriptionCallback,\n );\n } else if (\n event.type === 'observerRemoved' &&\n observerCount === 0 &&\n hasSubscription\n ) {\n const subscriptionListener = subscriptions.get(hash);\n\n messenger.unsubscribe(\n `${service}:cacheUpdated:${hash}`,\n subscriptionListener as JsonSubscriptionCallback,\n );\n subscriptions.delete(hash);\n }\n });\n\n // Override invalidateQueries to ensure the data service is invalidated as well.\n const originalInvalidate = client.invalidateQueries.bind(client);\n\n // This function is defined in this way to have full support for all function overloads.\n client.invalidateQueries = async (\n arg1?: QueryKey | InvalidateQueryFilters,\n arg2?: OmitKeyof<InvalidateQueryFilters, 'queryKey'> | InvalidateOptions,\n arg3?: InvalidateOptions,\n ): Promise<void> => {\n const [filters, options] = parseFilterArgs(arg1, arg2, arg3);\n\n const queries = client.getQueryCache().findAll(filters);\n\n const services = [\n ...new Set(queries.map((query) => parseQueryKey(query.queryKey))),\n ];\n\n await Promise.all(\n services.map(async (service) => {\n if (!service) {\n return null;\n }\n\n return messenger.call(\n `${service}:invalidateQueries`,\n filters as Json,\n options as Json,\n );\n }),\n );\n\n return originalInvalidate(filters, options);\n };\n\n return client;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import { Json } from "@metamask/utils";
2
+ import { QueryClient, QueryClientConfig } from "@tanstack/query-core";
3
+ type JsonSubscriptionCallback = (data: Json) => void;
4
+ type MessengerAdapter = {
5
+ call: (method: string, ...params: Json[]) => Promise<Json | void>;
6
+ subscribe: (method: string, callback: JsonSubscriptionCallback) => void;
7
+ unsubscribe: (method: string, callback: JsonSubscriptionCallback) => void;
8
+ };
9
+ /**
10
+ * Create a QueryClient queries and subscribes to data services using the messenger.
11
+ *
12
+ * @param dataServices - A list of data services.
13
+ * @param messenger - A messenger adapter.
14
+ * @param config - Optional query client configuration options.
15
+ * @returns The QueryClient.
16
+ */
17
+ export declare function createUIQueryClient(dataServices: string[], messenger: MessengerAdapter, config?: QueryClientConfig): QueryClient;
18
+ export {};
19
+ //# sourceMappingURL=createUIQueryClient.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createUIQueryClient.d.cts","sourceRoot":"","sources":["../src/createUIQueryClient.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,IAAI,EAAE,wBAAwB;AAC/C,OAAO,EAEL,WAAW,EAMX,iBAAiB,EAClB,6BAA6B;AAM9B,KAAK,wBAAwB,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;AAGrD,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAClE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACxE,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,wBAAwB,KAAK,IAAI,CAAC;CAC3E,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,gBAAgB,EAC3B,MAAM,GAAE,iBAAsB,GAC7B,WAAW,CA6Ib"}
@@ -0,0 +1,19 @@
1
+ import { Json } from "@metamask/utils";
2
+ import { QueryClient, QueryClientConfig } from "@tanstack/query-core";
3
+ type JsonSubscriptionCallback = (data: Json) => void;
4
+ type MessengerAdapter = {
5
+ call: (method: string, ...params: Json[]) => Promise<Json | void>;
6
+ subscribe: (method: string, callback: JsonSubscriptionCallback) => void;
7
+ unsubscribe: (method: string, callback: JsonSubscriptionCallback) => void;
8
+ };
9
+ /**
10
+ * Create a QueryClient queries and subscribes to data services using the messenger.
11
+ *
12
+ * @param dataServices - A list of data services.
13
+ * @param messenger - A messenger adapter.
14
+ * @param config - Optional query client configuration options.
15
+ * @returns The QueryClient.
16
+ */
17
+ export declare function createUIQueryClient(dataServices: string[], messenger: MessengerAdapter, config?: QueryClientConfig): QueryClient;
18
+ export {};
19
+ //# sourceMappingURL=createUIQueryClient.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createUIQueryClient.d.mts","sourceRoot":"","sources":["../src/createUIQueryClient.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,IAAI,EAAE,wBAAwB;AAC/C,OAAO,EAEL,WAAW,EAMX,iBAAiB,EAClB,6BAA6B;AAM9B,KAAK,wBAAwB,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;AAGrD,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAClE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACxE,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,wBAAwB,KAAK,IAAI,CAAC;CAC3E,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,gBAAgB,EAC3B,MAAM,GAAE,iBAAsB,GAC7B,WAAW,CA6Ib"}
@@ -0,0 +1,100 @@
1
+ import { assert } from "@metamask/utils";
2
+ import { hydrate, QueryClient, parseFilterArgs } from "@tanstack/query-core";
3
+ /**
4
+ * Create a QueryClient queries and subscribes to data services using the messenger.
5
+ *
6
+ * @param dataServices - A list of data services.
7
+ * @param messenger - A messenger adapter.
8
+ * @param config - Optional query client configuration options.
9
+ * @returns The QueryClient.
10
+ */
11
+ export function createUIQueryClient(dataServices, messenger, config = {}) {
12
+ const subscriptions = new Map();
13
+ /**
14
+ * Parse a query key to detect a service name.
15
+ *
16
+ * @param queryKey - The query key.
17
+ * @returns The service name if it parsing succeeded, otherwise null.
18
+ */
19
+ function parseQueryKey(queryKey) {
20
+ const action = queryKey[0];
21
+ if (typeof action !== 'string') {
22
+ return null;
23
+ }
24
+ const service = action.split(':')[0];
25
+ if (!dataServices.includes(service)) {
26
+ return null;
27
+ }
28
+ return service;
29
+ }
30
+ const client = new QueryClient({
31
+ ...config,
32
+ defaultOptions: {
33
+ queries: {
34
+ ...config.defaultOptions?.queries,
35
+ queryFn: async (options) => {
36
+ const { queryKey } = options;
37
+ const action = queryKey[0];
38
+ assert(typeof action === 'string' &&
39
+ dataServices.includes(action.split(':')?.[0]), "Queries must call actions on the messenger provided to createUIQueryClient, e.g. `queryKey: ['ExampleDataService:getAssets', ...]`.");
40
+ return await messenger.call(action, ...options.queryKey.slice(1), options.pageParam);
41
+ },
42
+ },
43
+ mutations: config.defaultOptions?.mutations,
44
+ },
45
+ });
46
+ const cache = client.getQueryCache();
47
+ cache.subscribe((event) => {
48
+ const { query } = event;
49
+ const hash = query.queryHash;
50
+ const hasSubscription = subscriptions.has(hash);
51
+ const observerCount = query.getObserversCount();
52
+ const service = parseQueryKey(query.queryKey);
53
+ if (!service) {
54
+ return;
55
+ }
56
+ if (!hasSubscription &&
57
+ event.type === 'observerAdded' &&
58
+ observerCount === 1) {
59
+ const cacheListener = (payload) => {
60
+ if (payload.type === 'removed') {
61
+ const currentQuery = cache.get(hash);
62
+ if (currentQuery) {
63
+ cache.remove(currentQuery);
64
+ }
65
+ }
66
+ else {
67
+ hydrate(client, payload.state);
68
+ }
69
+ };
70
+ subscriptions.set(hash, cacheListener);
71
+ messenger.subscribe(`${service}:cacheUpdated:${hash}`, cacheListener);
72
+ }
73
+ else if (event.type === 'observerRemoved' &&
74
+ observerCount === 0 &&
75
+ hasSubscription) {
76
+ const subscriptionListener = subscriptions.get(hash);
77
+ messenger.unsubscribe(`${service}:cacheUpdated:${hash}`, subscriptionListener);
78
+ subscriptions.delete(hash);
79
+ }
80
+ });
81
+ // Override invalidateQueries to ensure the data service is invalidated as well.
82
+ const originalInvalidate = client.invalidateQueries.bind(client);
83
+ // This function is defined in this way to have full support for all function overloads.
84
+ client.invalidateQueries = async (arg1, arg2, arg3) => {
85
+ const [filters, options] = parseFilterArgs(arg1, arg2, arg3);
86
+ const queries = client.getQueryCache().findAll(filters);
87
+ const services = [
88
+ ...new Set(queries.map((query) => parseQueryKey(query.queryKey))),
89
+ ];
90
+ await Promise.all(services.map(async (service) => {
91
+ if (!service) {
92
+ return null;
93
+ }
94
+ return messenger.call(`${service}:invalidateQueries`, filters, options);
95
+ }));
96
+ return originalInvalidate(filters, options);
97
+ };
98
+ return client;
99
+ }
100
+ //# sourceMappingURL=createUIQueryClient.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createUIQueryClient.mjs","sourceRoot":"","sources":["../src/createUIQueryClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { DataServiceGranularCacheUpdatedPayload } from '@metamask/base-data-service';\nimport { assert, Json } from '@metamask/utils';\nimport {\n hydrate,\n QueryClient,\n InvalidateQueryFilters,\n InvalidateOptions,\n OmitKeyof,\n parseFilterArgs,\n QueryKey,\n QueryClientConfig,\n} from '@tanstack/query-core';\n\ntype SubscriptionCallback = (\n payload: DataServiceGranularCacheUpdatedPayload,\n) => void;\n\ntype JsonSubscriptionCallback = (data: Json) => void;\n\n// TODO: Figure out if we can replace with a better Messenger type\ntype MessengerAdapter = {\n call: (method: string, ...params: Json[]) => Promise<Json | void>;\n subscribe: (method: string, callback: JsonSubscriptionCallback) => void;\n unsubscribe: (method: string, callback: JsonSubscriptionCallback) => void;\n};\n\n/**\n * Create a QueryClient queries and subscribes to data services using the messenger.\n *\n * @param dataServices - A list of data services.\n * @param messenger - A messenger adapter.\n * @param config - Optional query client configuration options.\n * @returns The QueryClient.\n */\nexport function createUIQueryClient(\n dataServices: string[],\n messenger: MessengerAdapter,\n config: QueryClientConfig = {},\n): QueryClient {\n const subscriptions = new Map<string, SubscriptionCallback>();\n\n /**\n * Parse a query key to detect a service name.\n *\n * @param queryKey - The query key.\n * @returns The service name if it parsing succeeded, otherwise null.\n */\n function parseQueryKey(queryKey: QueryKey): string | null {\n const action = queryKey[0];\n\n if (typeof action !== 'string') {\n return null;\n }\n\n const service = action.split(':')[0];\n\n if (!dataServices.includes(service)) {\n return null;\n }\n\n return service;\n }\n\n const client: QueryClient = new QueryClient({\n ...config,\n defaultOptions: {\n queries: {\n ...config.defaultOptions?.queries,\n queryFn: async (options): Promise<unknown> => {\n const { queryKey } = options;\n\n const action = queryKey[0];\n\n assert(\n typeof action === 'string' &&\n dataServices.includes(action.split(':')?.[0]),\n \"Queries must call actions on the messenger provided to createUIQueryClient, e.g. `queryKey: ['ExampleDataService:getAssets', ...]`.\",\n );\n\n return await messenger.call(\n action,\n ...(options.queryKey.slice(1) as Json[]),\n options.pageParam,\n );\n },\n },\n mutations: config.defaultOptions?.mutations,\n },\n });\n\n const cache = client.getQueryCache();\n\n cache.subscribe((event) => {\n const { query } = event;\n\n const hash = query.queryHash;\n const hasSubscription = subscriptions.has(hash);\n const observerCount = query.getObserversCount();\n\n const service = parseQueryKey(query.queryKey);\n\n if (!service) {\n return;\n }\n\n if (\n !hasSubscription &&\n event.type === 'observerAdded' &&\n observerCount === 1\n ) {\n const cacheListener = (\n payload: DataServiceGranularCacheUpdatedPayload,\n ): void => {\n if (payload.type === 'removed') {\n const currentQuery = cache.get(hash);\n\n if (currentQuery) {\n cache.remove(currentQuery);\n }\n } else {\n hydrate(client, payload.state);\n }\n };\n\n subscriptions.set(hash, cacheListener);\n messenger.subscribe(\n `${service}:cacheUpdated:${hash}`,\n cacheListener as JsonSubscriptionCallback,\n );\n } else if (\n event.type === 'observerRemoved' &&\n observerCount === 0 &&\n hasSubscription\n ) {\n const subscriptionListener = subscriptions.get(hash);\n\n messenger.unsubscribe(\n `${service}:cacheUpdated:${hash}`,\n subscriptionListener as JsonSubscriptionCallback,\n );\n subscriptions.delete(hash);\n }\n });\n\n // Override invalidateQueries to ensure the data service is invalidated as well.\n const originalInvalidate = client.invalidateQueries.bind(client);\n\n // This function is defined in this way to have full support for all function overloads.\n client.invalidateQueries = async (\n arg1?: QueryKey | InvalidateQueryFilters,\n arg2?: OmitKeyof<InvalidateQueryFilters, 'queryKey'> | InvalidateOptions,\n arg3?: InvalidateOptions,\n ): Promise<void> => {\n const [filters, options] = parseFilterArgs(arg1, arg2, arg3);\n\n const queries = client.getQueryCache().findAll(filters);\n\n const services = [\n ...new Set(queries.map((query) => parseQueryKey(query.queryKey))),\n ];\n\n await Promise.all(\n services.map(async (service) => {\n if (!service) {\n return null;\n }\n\n return messenger.call(\n `${service}:invalidateQueries`,\n filters as Json,\n options as Json,\n );\n }),\n );\n\n return originalInvalidate(filters, options);\n };\n\n return client;\n}\n"]}
package/dist/hooks.cjs ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useInfiniteQuery = exports.useQuery = void 0;
4
+ const react_query_1 = require("@tanstack/react-query");
5
+ /**
6
+ * We provide re-exports of the underlying TanStack Query hooks with narrower types,
7
+ * removing `staleTime` and `queryFn` which aren't useful when using data services.
8
+ */
9
+ const DATA_SERVICE_QUERY_DEFAULTS = {
10
+ staleTime: 0,
11
+ retry: false,
12
+ };
13
+ /**
14
+ * Consume a query from a data service.
15
+ *
16
+ * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported
17
+ * when querying data services.
18
+ * @returns The query results.
19
+ */
20
+ function useQuery(options) {
21
+ return (0, react_query_1.useQuery)({ ...DATA_SERVICE_QUERY_DEFAULTS, ...options });
22
+ }
23
+ exports.useQuery = useQuery;
24
+ /**
25
+ * Consume a paginated query from a data service.
26
+ *
27
+ * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported
28
+ * when querying data services.
29
+ * @returns The paginated query results.
30
+ */
31
+ function useInfiniteQuery(options) {
32
+ return (0, react_query_1.useInfiniteQuery)({
33
+ ...DATA_SERVICE_QUERY_DEFAULTS,
34
+ ...options,
35
+ });
36
+ }
37
+ exports.useInfiniteQuery = useInfiniteQuery;
38
+ //# sourceMappingURL=hooks.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.cjs","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":";;;AACA,uDAU+B;AAE/B;;;GAGG;AAEH,MAAM,2BAA2B,GAAG;IAClC,SAAS,EAAE,CAAC;IACZ,KAAK,EAAE,KAAK;CACb,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,QAAQ,CAMtB,OAQC;IAED,OAAO,IAAA,sBAAgB,EAAC,EAAE,GAAG,2BAA2B,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAC1E,CAAC;AAjBD,4BAiBC;AAED;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAM9B,OASC;IAED,OAAO,IAAA,8BAAwB,EAAC;QAC9B,GAAG,2BAA2B;QAC9B,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC;AArBD,4CAqBC","sourcesContent":["import { QueryKey } from '@metamask/base-data-service';\nimport {\n useQuery as useQueryTanStack,\n useInfiniteQuery as useInfiniteQueryTanStack,\n OmitKeyof,\n UseQueryOptions,\n InitialDataFunction,\n NonUndefinedGuard,\n UseInfiniteQueryOptions,\n UseQueryResult,\n UseInfiniteQueryResult,\n} from '@tanstack/react-query';\n\n/**\n * We provide re-exports of the underlying TanStack Query hooks with narrower types,\n * removing `staleTime` and `queryFn` which aren't useful when using data services.\n */\n\nconst DATA_SERVICE_QUERY_DEFAULTS = {\n staleTime: 0,\n retry: false,\n};\n\n/**\n * Consume a query from a data service.\n *\n * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported\n * when querying data services.\n * @returns The query results.\n */\nexport function useQuery<\n TQueryFnData = unknown,\n TError = unknown,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: OmitKeyof<\n UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n 'initialData' | 'staleTime' | 'queryFn'\n > & {\n initialData?:\n | undefined\n | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n | NonUndefinedGuard<TQueryFnData>;\n },\n): UseQueryResult<TData, TError> {\n return useQueryTanStack({ ...DATA_SERVICE_QUERY_DEFAULTS, ...options });\n}\n\n/**\n * Consume a paginated query from a data service.\n *\n * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported\n * when querying data services.\n * @returns The paginated query results.\n */\nexport function useInfiniteQuery<\n TQueryFnData = unknown,\n TError = unknown,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: OmitKeyof<\n UseInfiniteQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryFnData,\n TQueryKey\n >,\n 'staleTime' | 'queryFn'\n >,\n): UseInfiniteQueryResult<TData, TError> {\n return useInfiniteQueryTanStack({\n ...DATA_SERVICE_QUERY_DEFAULTS,\n ...options,\n });\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import { QueryKey } from "@metamask/base-data-service";
2
+ import { OmitKeyof, UseQueryOptions, InitialDataFunction, NonUndefinedGuard, UseInfiniteQueryOptions, UseQueryResult, UseInfiniteQueryResult } from "@tanstack/react-query";
3
+ /**
4
+ * Consume a query from a data service.
5
+ *
6
+ * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported
7
+ * when querying data services.
8
+ * @returns The query results.
9
+ */
10
+ export declare function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: OmitKeyof<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'initialData' | 'staleTime' | 'queryFn'> & {
11
+ initialData?: undefined | InitialDataFunction<NonUndefinedGuard<TQueryFnData>> | NonUndefinedGuard<TQueryFnData>;
12
+ }): UseQueryResult<TData, TError>;
13
+ /**
14
+ * Consume a paginated query from a data service.
15
+ *
16
+ * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported
17
+ * when querying data services.
18
+ * @returns The paginated query results.
19
+ */
20
+ export declare function useInfiniteQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: OmitKeyof<UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, 'staleTime' | 'queryFn'>): UseInfiniteQueryResult<TData, TError>;
21
+ //# sourceMappingURL=hooks.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.cts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,oCAAoC;AACvD,OAAO,EAGL,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,cAAc,EACd,sBAAsB,EACvB,8BAA8B;AAY/B;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,YAAY,GAAG,OAAO,EACtB,MAAM,GAAG,OAAO,EAChB,KAAK,GAAG,YAAY,EACpB,SAAS,SAAS,QAAQ,GAAG,QAAQ,EAErC,OAAO,EAAE,SAAS,CAChB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EACvD,aAAa,GAAG,WAAW,GAAG,SAAS,CACxC,GAAG;IACF,WAAW,CAAC,EACR,SAAS,GACT,mBAAmB,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC,GACpD,iBAAiB,CAAC,YAAY,CAAC,CAAC;CACrC,GACA,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAE/B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,GAAG,OAAO,EACtB,MAAM,GAAG,OAAO,EAChB,KAAK,GAAG,YAAY,EACpB,SAAS,SAAS,QAAQ,GAAG,QAAQ,EAErC,OAAO,EAAE,SAAS,CAChB,uBAAuB,CACrB,YAAY,EACZ,MAAM,EACN,KAAK,EACL,YAAY,EACZ,SAAS,CACV,EACD,WAAW,GAAG,SAAS,CACxB,GACA,sBAAsB,CAAC,KAAK,EAAE,MAAM,CAAC,CAKvC"}
@@ -0,0 +1,21 @@
1
+ import { QueryKey } from "@metamask/base-data-service";
2
+ import { OmitKeyof, UseQueryOptions, InitialDataFunction, NonUndefinedGuard, UseInfiniteQueryOptions, UseQueryResult, UseInfiniteQueryResult } from "@tanstack/react-query";
3
+ /**
4
+ * Consume a query from a data service.
5
+ *
6
+ * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported
7
+ * when querying data services.
8
+ * @returns The query results.
9
+ */
10
+ export declare function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: OmitKeyof<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'initialData' | 'staleTime' | 'queryFn'> & {
11
+ initialData?: undefined | InitialDataFunction<NonUndefinedGuard<TQueryFnData>> | NonUndefinedGuard<TQueryFnData>;
12
+ }): UseQueryResult<TData, TError>;
13
+ /**
14
+ * Consume a paginated query from a data service.
15
+ *
16
+ * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported
17
+ * when querying data services.
18
+ * @returns The paginated query results.
19
+ */
20
+ export declare function useInfiniteQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: OmitKeyof<UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, 'staleTime' | 'queryFn'>): UseInfiniteQueryResult<TData, TError>;
21
+ //# sourceMappingURL=hooks.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.mts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,oCAAoC;AACvD,OAAO,EAGL,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,cAAc,EACd,sBAAsB,EACvB,8BAA8B;AAY/B;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,YAAY,GAAG,OAAO,EACtB,MAAM,GAAG,OAAO,EAChB,KAAK,GAAG,YAAY,EACpB,SAAS,SAAS,QAAQ,GAAG,QAAQ,EAErC,OAAO,EAAE,SAAS,CAChB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EACvD,aAAa,GAAG,WAAW,GAAG,SAAS,CACxC,GAAG;IACF,WAAW,CAAC,EACR,SAAS,GACT,mBAAmB,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC,GACpD,iBAAiB,CAAC,YAAY,CAAC,CAAC;CACrC,GACA,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAE/B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,GAAG,OAAO,EACtB,MAAM,GAAG,OAAO,EAChB,KAAK,GAAG,YAAY,EACpB,SAAS,SAAS,QAAQ,GAAG,QAAQ,EAErC,OAAO,EAAE,SAAS,CAChB,uBAAuB,CACrB,YAAY,EACZ,MAAM,EACN,KAAK,EACL,YAAY,EACZ,SAAS,CACV,EACD,WAAW,GAAG,SAAS,CACxB,GACA,sBAAsB,CAAC,KAAK,EAAE,MAAM,CAAC,CAKvC"}
package/dist/hooks.mjs ADDED
@@ -0,0 +1,33 @@
1
+ import { useQuery as useQueryTanStack, useInfiniteQuery as useInfiniteQueryTanStack } from "@tanstack/react-query";
2
+ /**
3
+ * We provide re-exports of the underlying TanStack Query hooks with narrower types,
4
+ * removing `staleTime` and `queryFn` which aren't useful when using data services.
5
+ */
6
+ const DATA_SERVICE_QUERY_DEFAULTS = {
7
+ staleTime: 0,
8
+ retry: false,
9
+ };
10
+ /**
11
+ * Consume a query from a data service.
12
+ *
13
+ * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported
14
+ * when querying data services.
15
+ * @returns The query results.
16
+ */
17
+ export function useQuery(options) {
18
+ return useQueryTanStack({ ...DATA_SERVICE_QUERY_DEFAULTS, ...options });
19
+ }
20
+ /**
21
+ * Consume a paginated query from a data service.
22
+ *
23
+ * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported
24
+ * when querying data services.
25
+ * @returns The paginated query results.
26
+ */
27
+ export function useInfiniteQuery(options) {
28
+ return useInfiniteQueryTanStack({
29
+ ...DATA_SERVICE_QUERY_DEFAULTS,
30
+ ...options,
31
+ });
32
+ }
33
+ //# sourceMappingURL=hooks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.mjs","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,IAAI,gBAAgB,EAC5B,gBAAgB,IAAI,wBAAwB,EAQ7C,8BAA8B;AAE/B;;;GAGG;AAEH,MAAM,2BAA2B,GAAG;IAClC,SAAS,EAAE,CAAC;IACZ,KAAK,EAAE,KAAK;CACb,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAMtB,OAQC;IAED,OAAO,gBAAgB,CAAC,EAAE,GAAG,2BAA2B,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAM9B,OASC;IAED,OAAO,wBAAwB,CAAC;QAC9B,GAAG,2BAA2B;QAC9B,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { QueryKey } from '@metamask/base-data-service';\nimport {\n useQuery as useQueryTanStack,\n useInfiniteQuery as useInfiniteQueryTanStack,\n OmitKeyof,\n UseQueryOptions,\n InitialDataFunction,\n NonUndefinedGuard,\n UseInfiniteQueryOptions,\n UseQueryResult,\n UseInfiniteQueryResult,\n} from '@tanstack/react-query';\n\n/**\n * We provide re-exports of the underlying TanStack Query hooks with narrower types,\n * removing `staleTime` and `queryFn` which aren't useful when using data services.\n */\n\nconst DATA_SERVICE_QUERY_DEFAULTS = {\n staleTime: 0,\n retry: false,\n};\n\n/**\n * Consume a query from a data service.\n *\n * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported\n * when querying data services.\n * @returns The query results.\n */\nexport function useQuery<\n TQueryFnData = unknown,\n TError = unknown,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: OmitKeyof<\n UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n 'initialData' | 'staleTime' | 'queryFn'\n > & {\n initialData?:\n | undefined\n | InitialDataFunction<NonUndefinedGuard<TQueryFnData>>\n | NonUndefinedGuard<TQueryFnData>;\n },\n): UseQueryResult<TData, TError> {\n return useQueryTanStack({ ...DATA_SERVICE_QUERY_DEFAULTS, ...options });\n}\n\n/**\n * Consume a paginated query from a data service.\n *\n * @param options - The query options. Keep in mind that `staleTime` and `queryFn` are not supported\n * when querying data services.\n * @returns The paginated query results.\n */\nexport function useInfiniteQuery<\n TQueryFnData = unknown,\n TError = unknown,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(\n options: OmitKeyof<\n UseInfiniteQueryOptions<\n TQueryFnData,\n TError,\n TData,\n TQueryFnData,\n TQueryKey\n >,\n 'staleTime' | 'queryFn'\n >,\n): UseInfiniteQueryResult<TData, TError> {\n return useInfiniteQueryTanStack({\n ...DATA_SERVICE_QUERY_DEFAULTS,\n ...options,\n });\n}\n"]}
package/dist/index.cjs CHANGED
@@ -1,13 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- /**
4
- * Example function that returns a greeting for the given name.
5
- *
6
- * @param name - The name to greet.
7
- * @returns The greeting.
8
- */
9
- function greeter(name) {
10
- return `Hello, ${name}!`;
11
- }
12
- exports.default = greeter;
3
+ exports.useInfiniteQuery = exports.useQuery = exports.createUIQueryClient = void 0;
4
+ var createUIQueryClient_1 = require("./createUIQueryClient.cjs");
5
+ Object.defineProperty(exports, "createUIQueryClient", { enumerable: true, get: function () { return createUIQueryClient_1.createUIQueryClient; } });
6
+ var hooks_1 = require("./hooks.cjs");
7
+ Object.defineProperty(exports, "useQuery", { enumerable: true, get: function () { return hooks_1.useQuery; } });
8
+ Object.defineProperty(exports, "useInfiniteQuery", { enumerable: true, get: function () { return hooks_1.useInfiniteQuery; } });
13
9
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA;;;;;GAKG;AACH,SAAwB,OAAO,CAAC,IAAY;IAC1C,OAAO,UAAU,IAAI,GAAG,CAAC;AAC3B,CAAC;AAFD,0BAEC","sourcesContent":["/**\n * Example function that returns a greeting for the given name.\n *\n * @param name - The name to greet.\n * @returns The greeting.\n */\nexport default function greeter(name: string): string {\n return `Hello, ${name}!`;\n}\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iEAA4D;AAAnD,0HAAA,mBAAmB,OAAA;AAC5B,qCAAqD;AAA5C,iGAAA,QAAQ,OAAA;AAAE,yGAAA,gBAAgB,OAAA","sourcesContent":["export { createUIQueryClient } from './createUIQueryClient';\nexport { useQuery, useInfiniteQuery } from './hooks';\n"]}
package/dist/index.d.cts CHANGED
@@ -1,8 +1,3 @@
1
- /**
2
- * Example function that returns a greeting for the given name.
3
- *
4
- * @param name - The name to greet.
5
- * @returns The greeting.
6
- */
7
- export default function greeter(name: string): string;
1
+ export { createUIQueryClient } from "./createUIQueryClient.cjs";
2
+ export { useQuery, useInfiniteQuery } from "./hooks.cjs";
8
3
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,kCAA8B;AAC5D,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,oBAAgB"}
package/dist/index.d.mts CHANGED
@@ -1,8 +1,3 @@
1
- /**
2
- * Example function that returns a greeting for the given name.
3
- *
4
- * @param name - The name to greet.
5
- * @returns The greeting.
6
- */
7
- export default function greeter(name: string): string;
1
+ export { createUIQueryClient } from "./createUIQueryClient.mjs";
2
+ export { useQuery, useInfiniteQuery } from "./hooks.mjs";
8
3
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,kCAA8B;AAC5D,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,oBAAgB"}
package/dist/index.mjs CHANGED
@@ -1,10 +1,3 @@
1
- /**
2
- * Example function that returns a greeting for the given name.
3
- *
4
- * @param name - The name to greet.
5
- * @returns The greeting.
6
- */
7
- export default function greeter(name) {
8
- return `Hello, ${name}!`;
9
- }
1
+ export { createUIQueryClient } from "./createUIQueryClient.mjs";
2
+ export { useQuery, useInfiniteQuery } from "./hooks.mjs";
10
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,IAAY;IAC1C,OAAO,UAAU,IAAI,GAAG,CAAC;AAC3B,CAAC","sourcesContent":["/**\n * Example function that returns a greeting for the given name.\n *\n * @param name - The name to greet.\n * @returns The greeting.\n */\nexport default function greeter(name: string): string {\n return `Hello, ${name}!`;\n}\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,kCAA8B;AAC5D,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,oBAAgB","sourcesContent":["export { createUIQueryClient } from './createUIQueryClient';\nexport { useQuery, useInfiniteQuery } from './hooks';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/react-data-query",
3
- "version": "0.0.0-preview-a0caca0c0",
3
+ "version": "0.1.0-preview-afe010990",
4
4
  "description": "Provides React utilities for consuming data services",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -46,6 +46,12 @@
46
46
  "test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
47
47
  "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
48
48
  },
49
+ "dependencies": {
50
+ "@metamask/base-data-service": "^0.1.0",
51
+ "@metamask/utils": "^11.9.0",
52
+ "@tanstack/query-core": "^4.43.0",
53
+ "@tanstack/react-query": "^4.43.0"
54
+ },
49
55
  "devDependencies": {
50
56
  "@metamask/auto-changelog": "^3.4.4",
51
57
  "@ts-bridge/cli": "^0.6.4",
@@ -57,6 +63,11 @@
57
63
  "typedoc-plugin-missing-exports": "^2.0.0",
58
64
  "typescript": "~5.3.3"
59
65
  },
66
+ "peerDependencies": {
67
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
68
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
69
+ "react-native": "*"
70
+ },
60
71
  "engines": {
61
72
  "node": "^18.18 || >=20"
62
73
  },