├── .gitignore
├── .ocamlformat
├── Makefile
├── README.md
├── dune-project
├── melange-react-query.opam
├── melange-react-query.opam.template
├── package.json
├── src
├── ReactQuery.ml
├── ReactQuery_Client.ml
├── ReactQuery_DevTools.ml
├── ReactQuery_Hooks.ml
├── ReactQuery_InfiniteQuery.ml
├── ReactQuery_Mutation.ml
├── ReactQuery_Query.ml
├── ReactQuery_Types.ml
├── ReactQuery_Utils.ml
└── dune
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/node
3 |
4 | ### Node ###
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 |
24 | # nyc test coverage
25 | .nyc_output
26 |
27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
28 | .grunt
29 |
30 | # Bower dependency directory (https://bower.io/)
31 | bower_components
32 |
33 | # node-waf configuration
34 | .lock-wscript
35 |
36 | # Compiled binary addons (http://nodejs.org/api/addons.html)
37 | build/Release
38 |
39 | # Dependency directories
40 | node_modules/
41 | jspm_packages/
42 |
43 | # Typescript v1 declaration files
44 | typings/
45 |
46 | # Optional npm cache directory
47 | .npm
48 |
49 | # Optional eslint cache
50 | .eslintcache
51 |
52 | # Optional REPL history
53 | .node_repl_history
54 |
55 | # Output of 'npm pack'
56 | *.tgz
57 |
58 | # Yarn Integrity file
59 | .yarn-integrity
60 |
61 | # dotenv environment variables file
62 | .env
63 |
64 |
65 | # End of https://www.gitignore.io/api/node
66 |
67 | .merlin
68 |
69 | _build
70 | _opam
71 |
72 | .vscode/
--------------------------------------------------------------------------------
/.ocamlformat:
--------------------------------------------------------------------------------
1 | profile=default
2 | break-infix=fit-or-vertical
3 | break-cases=fit-or-vertical
4 | break-fun-decl=fit-or-vertical
5 | break-fun-sig=fit-or-vertical
6 | if-then-else=vertical
7 | let-and=sparse
8 | let-binding-spacing=double-semicolon
9 | margin=90
10 | parens-ite=true
11 | type-decl=sparse
12 | wrap-fun-args=false
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | project_name = melange-moment
2 |
3 | DUNE = opam exec -- dune
4 |
5 | .DEFAULT_GOAL := help
6 |
7 | .PHONY: help
8 | help: ## Print this help message
9 | @echo "List of available make commands";
10 | @echo "";
11 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}';
12 | @echo "";
13 |
14 | .PHONY: create-switch
15 | create-switch: ## Create opam switch
16 | opam switch create . 5.1.0 -y --deps-only
17 |
18 | .PHONY: init
19 | init: create-switch install ## Configure everything to develop this repository in local
20 |
21 | .PHONY: install
22 | install: ## Install development dependencies
23 | yarn
24 | opam update
25 | opam install -y . --deps-only
26 |
27 | .PHONY: build
28 | build: ## Build the project
29 | $(DUNE) build
30 |
31 | .PHONY: build_verbose
32 | build_verbose: ## Build the project in verbose mode
33 | $(DUNE) build --verbose
34 |
35 | .PHONY: clean
36 | clean: ## Clean build artifacts and other generated files
37 | $(DUNE) clean
38 |
39 | .PHONY: format
40 | format: ## Format the codebase with ocamlformat
41 | $(DUNE) build @fmt --auto-promote
42 |
43 | .PHONY: format-check
44 | format-check: ## Checks if format is correct
45 | $(DUNE) build @fmt
46 |
47 | .PHONY: watch
48 | watch: ## Watch for the filesystem and rebuild on every change
49 | $(DUNE) build --watch
50 |
51 | .PHONY: test
52 | test: ## Run the tests
53 | $(DUNE) build @runtest --no-buffer
54 |
55 | .PHONY: test-watch
56 | test-watch: ## Run the tests and watch for changes
57 | $(DUNE) build -w @runtest
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # melange-react-query
2 |
3 | Bindings to [@tanstack/react-query](https://tanstack.com/query/latest) for [Melange](https://melange.re/).
4 |
5 | ## Installation
6 |
7 | ```sh
8 | opam install melange-react-query
9 | ```
10 |
11 | Then add `melange-react-query` to the `libraries` field in your dune file:
12 |
13 | ```lisp
14 | (melange.emit ;; or (library ...)
15 | ...
16 | (libraries melange-react-query))
17 | ```
18 |
19 | ## Usage
20 |
21 | ### `Provider.createClient()`
22 |
23 | The function responsible to create the query client
24 |
25 | Usage:
26 |
27 | ```reason
28 | let client = Provider.createClient();
29 | ```
30 |
31 | ### `Provider.make()`
32 |
33 | The React Context Provider responsible to hold all the react-query context
34 |
35 | ```reason
36 | children
37 | ```
38 |
39 | ### `DevTools.make(...)`
40 |
41 | The React Query DevTools Provider, which is responsible to initialize the React Query devtools
42 |
43 | ```reason
44 |
45 | ```
46 |
47 | ### `useQueryClient()`
48 |
49 | The queryClient fetched from a hook
50 |
51 | ```reason
52 | let queryClient = ReactQuery.useQueryClient();
53 | let queryResult = queryClient.fetchQuery(
54 | ReactQuery.fetchQueryOptions(
55 | ~queryKey=[|"articles"|],
56 | ~retryOnMount=true,
57 | (),
58 | )
59 | );
60 | ```
61 |
62 | ### `useQuery`
63 |
64 | ```reason
65 | let queryResult = ReactQuery.useQuery(
66 | ReactQuery.queryOptions(
67 | ~queryKey=[|"articles"|],
68 | ~queryFn=fetchArticles,
69 | ()
70 | )
71 | );
72 | ```
73 |
74 | ### `useMutation`
75 |
76 | The hook responsible to mutate a query, when update/create/delete anything
77 |
78 | ```reason
79 | let mutationResult = ReactQuery.useMutation(
80 | ReactQuery.mutationOptions(
81 | ~mutationKey=[|"articles"|],
82 | ~mutationFn=(article) => addArticle(article),
83 | ()
84 | )
85 | );
86 | ```
87 |
--------------------------------------------------------------------------------
/dune-project:
--------------------------------------------------------------------------------
1 | (lang dune 3.8)
2 |
3 | (using melange 0.1)
4 |
5 | (generate_opam_files true)
6 |
7 | (name melange-react-query)
8 |
9 | (version 0.1.0)
10 |
11 | (source
12 | (github ewert-online/melange-react-query))
13 |
14 | (authors "Torben Ewert ")
15 |
16 | (maintainers "Torben Ewert ")
17 |
18 | (homepage "https://github.com/ewert-online/melange-react-query")
19 |
20 | (bug_reports "https://github.com/ewert-online/melange-react-query")
21 |
22 | (license "MIT")
23 |
24 | (package
25 | (name melange-react-query)
26 | (synopsis "React Query support for Melange")
27 | (depends
28 | (ocaml
29 | (>= "5.1"))
30 | (melange
31 | (>= "2.0.0"))
32 | reason-react
33 | reason-react-ppx
34 | (opam-check-npm-deps :with-test)))
35 |
--------------------------------------------------------------------------------
/melange-react-query.opam:
--------------------------------------------------------------------------------
1 | # This file is generated by dune, edit dune-project instead
2 | opam-version: "2.0"
3 | version: "0.1.0"
4 | synopsis: "React Query support for Melange"
5 | maintainer: ["Torben Ewert "]
6 | authors: ["Torben Ewert "]
7 | license: "MIT"
8 | homepage: "https://github.com/ewert-online/melange-react-query"
9 | bug-reports: "https://github.com/ewert-online/melange-react-query"
10 | depends: [
11 | "dune" {>= "3.8"}
12 | "ocaml" {>= "5.1"}
13 | "melange" {>= "2.0.0"}
14 | "reason-react"
15 | "reason-react-ppx"
16 | "opam-check-npm-deps" {with-test}
17 | "odoc" {with-doc}
18 | ]
19 | build: [
20 | ["dune" "subst"] {dev}
21 | [
22 | "dune"
23 | "build"
24 | "-p"
25 | name
26 | "-j"
27 | jobs
28 | "@install"
29 | "@runtest" {with-test}
30 | "@doc" {with-doc}
31 | ]
32 | ]
33 | dev-repo: "git+https://github.com/ewert-online/melange-react-query.git"
34 | depexts: [
35 | ["@tanstack/react-query"] {npm-version = "^4.2.1"}
36 | ]
--------------------------------------------------------------------------------
/melange-react-query.opam.template:
--------------------------------------------------------------------------------
1 | depexts: [
2 | ["@tanstack/react-query"] {npm-version = "^4.2.1"}
3 | ]
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "react": "^18.2.0",
4 | "react-dom": "^18.2.0",
5 | "@tanstack/react-query": "^4.2.1"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ReactQuery.ml:
--------------------------------------------------------------------------------
1 | include ReactQuery_InfiniteQuery
2 | include ReactQuery_Query
3 | include ReactQuery_Mutation
4 | include ReactQuery_Hooks
5 | include ReactQuery_Utils
6 | include ReactQuery_Client
7 | include ReactQuery_DevTools
8 |
--------------------------------------------------------------------------------
/src/ReactQuery_Client.ml:
--------------------------------------------------------------------------------
1 | type queryClientValue
2 | type fetchMeta
3 |
4 | type notifyOnChangePropsKeys =
5 | [ `error
6 | | `isError
7 | | `isIdle
8 | | `isLoading
9 | | `isLoadingError
10 | | `isRefetchError
11 | | `isSuccess
12 | | `status
13 | | `tracked
14 | ]
15 |
16 | type infiniteQueryObserverResultProps =
17 | [ `error
18 | | `isError
19 | | `isIdle
20 | | `isLoading
21 | | `isLoadingError
22 | | `isRefetchError
23 | | `isSuccess
24 | | `status
25 | | `tracked
26 | ]
27 |
28 | type fetchContext
29 | type queryBehavior = { onFetch : fetchContext -> unit }
30 |
31 | let queryBehavior ~onFetch = { onFetch }
32 |
33 | type 'data getPreviousPageParamFunction = {
34 | firstPage : 'data;
35 | allPages : 'data array;
36 | }
37 |
38 | let getPreviousPageParamFunction ~firstPage ~allPages = { firstPage; allPages }
39 |
40 | type 'data getNextPageParamFunction = {
41 | lastPage : 'data;
42 | allPages : 'data array;
43 | }
44 |
45 | let getNextPageParamFunction ~lastPage ~allPages = { lastPage; allPages }
46 |
47 | type ('error, 'data, 'queryData, 'queryKey, 'pageParam) queryObserverOptions = {
48 | retry : 'error ReactQuery_Types.retryValue option; [@optional]
49 | retryDelay : 'error ReactQuery_Types.retryValue option; [@optional]
50 | cacheTime : int option; [@optional]
51 | isDataEqual : ('data option -> 'data -> bool) option; [@optional]
52 | queryHash : string option; [@optional]
53 | queryKey : 'queryKey option; [@optional]
54 | queryKeyHashFn : ('queryKey -> string) option; [@optional]
55 | initialData : (unit -> 'data) option; [@optional]
56 | initialDataUpdatedAt : (unit -> int option) option; [@optional]
57 | behavior : queryBehavior option; [@optional]
58 | structuralSharing : bool option; [@optional]
59 | getPreviousPageParam : 'data getPreviousPageParamFunction option; [@optional]
60 | getNextPageParam : 'data getNextPageParamFunction option; [@optional]
61 | defaulted : bool option; [@optional]
62 | enabled : bool option; [@optional]
63 | staleTime : int option; [@optional]
64 | refetchInterval : ReactQuery_Types.refetchIntervalValue option; [@optional]
65 | refetchIntervalInBackground : bool option; [@optional]
66 | refetchOnWindowFocus : ReactQuery_Types.boolOrAlwaysValue option; [@optional]
67 | refetchOnReconnect : ReactQuery_Types.boolOrAlwaysValue option; [@optional]
68 | refetchOnMount : ReactQuery_Types.boolOrAlwaysValue option; [@optional]
69 | retryOnMount : bool option; [@optional]
70 | notifyOnChangeProps : notifyOnChangePropsKeys array option; [@optional]
71 | notifyOnChangePropsExclusions : bool array option; [@optional]
72 | onSuccess : ('data -> unit) option; [@optional]
73 | onError : ('error -> unit) option; [@optional]
74 | onSettled : ('data option -> 'error option -> unit) option; [@optional]
75 | useErrorBoundary : bool option; [@optional]
76 | select : ('queryData -> 'data) option; [@optional]
77 | suspense : bool option; [@optional]
78 | keepPreviousData : bool option; [@optional]
79 | placeholderData : ReactQuery_Types.placeholderDataValue option; [@optional]
80 | optimisticResults : bool option; [@optional]
81 | queryFn :
82 | ('queryKey, 'pageParam) ReactQuery_Types.queryFunctionContext ->
83 | 'queryData Js.Promise.t;
84 | }
85 |
86 | type ('error, 'data, 'queryData, 'queryKey, 'pageParam) defaultOptions = {
87 | queries : ('error, 'data, 'queryData, 'queryKey, 'pageParam) queryObserverOptions option;
88 | }
89 |
90 | let defaultOptions ?queries () = { queries }
91 |
92 | type invalidateQueryFilter = { refetchType : [ `active | `inactive | `all | `none ] }
93 |
94 | let invalidateQueryFilter ~refetchType = { refetchType }
95 |
96 | type clientRefetchOptions = { throwOnError : bool option }
97 |
98 | let clientRefetchOptions ~throwOnError = { throwOnError }
99 |
100 | type 'queryKey invalidateQueryOptions = {
101 | queryKey : 'queryKey option;
102 | filters : invalidateQueryFilter option;
103 | refetchOptions : clientRefetchOptions option;
104 | }
105 |
106 | let invalidateQueryOptions ?queryKey ?filters ?refetchOptions () =
107 | { queryKey; filters; refetchOptions }
108 | ;;
109 |
110 | type 'queryKey refetchQueriesOptions = {
111 | queryKey : 'queryKey option;
112 | filters : 'queryKey ReactQuery_Types.queryFilter option;
113 | refetchOptions : clientRefetchOptions option;
114 | }
115 |
116 | let refetchQueriesOptions ?queryKey ?filters ?refetchOptions () =
117 | { queryKey; filters; refetchOptions }
118 | ;;
119 |
120 | type 'queryKey cancelQueriesOptions = {
121 | queryKey : 'queryKey option;
122 | filters : 'queryKey ReactQuery_Types.queryFilter option;
123 | }
124 |
125 | let cancelQueriesOptions ?queryKey ?filters () = { queryKey; filters }
126 |
127 | type ('queryData, 'queryError) queryState = {
128 | data : 'queryData option;
129 | dataUpdateCount : int;
130 | dataUpdatedAt : int;
131 | error : 'queryError Js.Nullable.t;
132 | errorUpdateCount : int;
133 | errorUpdatedAt : int;
134 | fetchFailureCount : int;
135 | fetchMeta : fetchMeta;
136 | isFetching : bool;
137 | isInvalidated : bool;
138 | isPaused : bool;
139 | status : ReactQuery_Types.queryStatus;
140 | }
141 |
142 | type ('queryKey, 'queryData, 'queryError, 'pageParam) fetchQueryOptions = {
143 | queryKey : 'queryKey option;
144 | queryFn :
145 | (('queryKey, 'pageParam) ReactQuery_Types.queryFunctionContext ->
146 | 'queryData Js.Promise.t)
147 | option;
148 | retry : 'queryError ReactQuery_Types.retryValue option;
149 | retryOnMount : bool option;
150 | retryDelay : 'queryError ReactQuery_Types.retryDelayValue option;
151 | staleTime : ReactQuery_Types.timeValue option;
152 | queryKeyHashFn : ('queryKey -> string) option;
153 | refetchOnMount : ReactQuery_Types.boolOrAlwaysValue option;
154 | structuralSharing : bool option;
155 | initialData : ('queryData -> 'queryData) option;
156 | initialDataUpdatedAt : (unit -> int) option;
157 | }
158 |
159 | let fetchQueryOptions
160 | ?queryKey
161 | ?queryFn
162 | ?retry
163 | ?retryOnMount
164 | ?retryDelay
165 | ?staleTime
166 | ?queryKeyHashFn
167 | ?refetchOnMount
168 | ?structuralSharing
169 | ?initialData
170 | ?initialDataUpdatedAt
171 | () =
172 | {
173 | queryKey;
174 | queryFn;
175 | retry;
176 | retryOnMount;
177 | retryDelay;
178 | staleTime;
179 | queryKeyHashFn;
180 | refetchOnMount;
181 | structuralSharing;
182 | initialData;
183 | initialDataUpdatedAt;
184 | }
185 | ;;
186 |
187 | type ('queryKey, 'queryData, 'queryError, 'pageParams) queryClient = {
188 | fetchQuery :
189 | ('queryKey, 'queryData, 'queryError, 'pageParams) fetchQueryOptions ->
190 | 'queryData Js.Promise.t;
191 | fetchInfiniteQuery :
192 | ('queryKey, 'queryData, 'queryError, 'pageParams) fetchQueryOptions ->
193 | 'queryData ReactQuery_Types.infiniteData Js.Promise.t;
194 | prefetchQuery :
195 | ('queryKey, 'queryData, 'queryError, 'pageParams) fetchQueryOptions ->
196 | unit Js.Promise.t;
197 | prefetchInfiniteQuery :
198 | ('queryKey, 'queryData, 'queryError, 'pageParams) fetchQueryOptions ->
199 | unit Js.Promise.t;
200 | getQueryData : 'queryKey -> 'queryData option;
201 | setQueryData : 'queryKey -> 'queryData option -> 'queryData;
202 | getQueryState :
203 | 'queryKey ->
204 | 'queryKey ReactQuery_Types.queryFilter ->
205 | ('queryData, 'queryError) queryState;
206 | setQueriesData :
207 | 'queryKey ReactQuery_Types.queryDataKeyOrFilterValue ->
208 | ('queryData option -> 'queryData) ->
209 | unit;
210 | invalidateQueries :
211 | 'queryKey ReactQuery_Types.queryFilter option ->
212 | clientRefetchOptions option ->
213 | unit Js.Promise.t;
214 | refetchQueries :
215 | 'queryKey ReactQuery_Types.queryFilter option ->
216 | clientRefetchOptions option ->
217 | unit Js.Promise.t;
218 | cancelQueries : 'queryKey ReactQuery_Types.queryFilter option -> unit Js.Promise.t;
219 | removeQueries : 'queryKey ReactQuery_Types.queryFilter option -> unit Js.Promise.t;
220 | resetQueries :
221 | 'queryKey ReactQuery_Types.queryFilter option ->
222 | clientRefetchOptions option ->
223 | unit Js.Promise.t;
224 | isFetching : 'queryKey ReactQuery_Types.queryFilter option -> bool;
225 | isMutating : 'queryKey ReactQuery_Types.queryFilter option -> bool;
226 | clear : unit -> unit;
227 | }
228 |
229 | external useQueryClient :
230 | unit -> ('queryKey, 'queryData, 'queryError, 'pageParams) queryClient
231 | = "useQueryClient"
232 | [@@module "@tanstack/react-query"]
233 |
234 | module Provider = struct
235 | external createClient : unit -> queryClientValue = "QueryClient"
236 | [@@new] [@@module "@tanstack/react-query"]
237 |
238 | external make :
239 | client:queryClientValue ->
240 | ?contextSharing:bool ->
241 | children:React.element ->
242 | React.element
243 | = "QueryClientProvider"
244 | [@@module "@tanstack/react-query"] [@@react.component]
245 | end
246 |
--------------------------------------------------------------------------------
/src/ReactQuery_DevTools.ml:
--------------------------------------------------------------------------------
1 | external make : ?initialIsOpen:bool -> React.element = "ReactQueryDevtools"
2 | [@@react.component] [@@module "@tanstack/react-query-devtools"]
3 |
--------------------------------------------------------------------------------
/src/ReactQuery_Hooks.ml:
--------------------------------------------------------------------------------
1 | type resetErrorBoundary = { reset : unit -> unit }
2 |
3 | external useIsFetching : unit -> bool = "useIsFetching" [@@module "@tanstack/react-query"]
4 |
5 | external useIsFetchingWithKeys : 'queryKey -> bool = "useIsFetching"
6 | [@@module "@tanstack/react-query"]
7 |
8 | external useIsMutating : unit -> bool = "useIsMutating" [@@module "@tanstack/react-query"]
9 |
10 | external useIsMutatingWithKeys : 'queryKey -> bool = "useIsMutating"
11 | [@@module "@tanstack/react-query"]
12 |
13 | external useQueryErrorResetBoundary :
14 | unit -> resetErrorBoundary
15 | = "useQueryErrorResetBoundary"
16 | [@@module "@tanstack/react-query"]
17 |
--------------------------------------------------------------------------------
/src/ReactQuery_InfiniteQuery.ml:
--------------------------------------------------------------------------------
1 | type 'queryKey inifiniteQueryFunctionContext = {
2 | queryKey : 'queryKey;
3 | pageParam : int option;
4 | }
5 |
6 | let inifiniteQueryFunctionContext ?pageParam ~queryKey () = { queryKey; pageParam }
7 |
8 | type ('queryKey, 'queryData, 'queryError) infiniteQueryOptions = {
9 | queryKey : 'queryKey option;
10 | queryFn : ('queryKey inifiniteQueryFunctionContext -> 'queryData Js.Promise.t) option;
11 | enabled : bool option;
12 | retry : 'queryError ReactQuery_Types.retryValue option;
13 | retryOnMount : bool option;
14 | retryDelay : 'queryError ReactQuery_Types.retryDelayValue option;
15 | staleTime : ReactQuery_Types.timeValue option;
16 | queryKeyHashFn : ('queryKey -> string) option;
17 | refetchInterval : ReactQuery_Types.refetchIntervalValue option;
18 | refetchIntervalInBackground : bool option;
19 | refetchOnMount : ReactQuery_Types.boolOrAlwaysValue option;
20 | refetchOnWindowFocus : ReactQuery_Types.boolOrAlwaysValue option;
21 | refetchOnReconnect : ReactQuery_Types.boolOrAlwaysValue option;
22 | notifyOnChangeProps : ReactQuery_Types.notifyOnChangePropsValue option;
23 | notifyOnChangePropsExclusions : string array option;
24 | onSuccess : ('queryData -> unit) option;
25 | onError : ('queryError -> unit) option;
26 | onSettled : ('queryData -> 'queryError -> unit) option;
27 | select : ('queryData -> 'queryData) option;
28 | suspense : bool option;
29 | keepPreviousData : bool option;
30 | structuralSharing : bool option;
31 | useErrorBoundary : bool option;
32 | initialData : ('queryData -> 'queryData) option;
33 | initialDataUpdatedAt : (unit -> int) option;
34 | placeholderData : (unit -> 'queryData) option;
35 | getNextPageParam : ('queryData -> int option) option;
36 | getPreviousPageParam : ('queryData -> int option) option;
37 | }
38 |
39 | let infiniteQueryOptions
40 | ?queryKey
41 | ?queryFn
42 | ?enabled
43 | ?retry
44 | ?retryOnMount
45 | ?retryDelay
46 | ?staleTime
47 | ?queryKeyHashFn
48 | ?refetchInterval
49 | ?refetchIntervalInBackground
50 | ?refetchOnMount
51 | ?refetchOnWindowFocus
52 | ?refetchOnReconnect
53 | ?notifyOnChangeProps
54 | ?notifyOnChangePropsExclusions
55 | ?onSuccess
56 | ?onError
57 | ?onSettled
58 | ?select
59 | ?suspense
60 | ?keepPreviousData
61 | ?structuralSharing
62 | ?useErrorBoundary
63 | ?initialData
64 | ?initialDataUpdatedAt
65 | ?placeholderData
66 | ?getNextPageParam
67 | ?getPreviousPageParam
68 | () =
69 | {
70 | queryKey;
71 | queryFn;
72 | enabled;
73 | retry;
74 | retryOnMount;
75 | retryDelay;
76 | staleTime;
77 | queryKeyHashFn;
78 | refetchInterval;
79 | refetchIntervalInBackground;
80 | refetchOnMount;
81 | refetchOnWindowFocus;
82 | refetchOnReconnect;
83 | notifyOnChangeProps;
84 | notifyOnChangePropsExclusions;
85 | onSuccess;
86 | onError;
87 | onSettled;
88 | select;
89 | suspense;
90 | keepPreviousData;
91 | structuralSharing;
92 | useErrorBoundary;
93 | initialData;
94 | initialDataUpdatedAt;
95 | placeholderData;
96 | getNextPageParam;
97 | getPreviousPageParam;
98 | }
99 | ;;
100 |
101 | type ('queryError, 'queryData) infiniteQueryResult = {
102 | status : ReactQuery_Types.queryStatus;
103 | isIdle : bool;
104 | isError : bool;
105 | isFetched : bool;
106 | isFetchedAfterMount : bool;
107 | isFetching : bool;
108 | isLoading : bool;
109 | isLoadingError : bool;
110 | isPlaceholderData : bool;
111 | isPreviousData : bool;
112 | isRefetchError : bool;
113 | isStale : bool;
114 | isSuccess : bool;
115 | dataUpdatedAt : int;
116 | error : 'queryError Js.Nullable.t;
117 | errorUpdatedAt : int;
118 | failureCount : int;
119 | refetch :
120 | ReactQuery_Types.refetchOptions ->
121 | ('queryError, 'queryData) infiniteQueryResult Js.Promise.t;
122 | remove : unit -> unit;
123 | data : 'queryData ReactQuery_Types.infiniteData option;
124 | isFetchingNextPage : bool;
125 | isFetchingPreviousPage : bool;
126 | fetchNextPage : unit -> unit;
127 | hasNextPage : bool;
128 | hasPreviousPage : bool;
129 | }
130 |
131 | external useInfiniteQuery :
132 | ('queryKey, 'queryData, 'queryError) infiniteQueryOptions ->
133 | ('queryError, 'queryData) infiniteQueryResult
134 | = "useInfiniteQuery"
135 | [@@module "@tanstack/react-query"]
136 |
--------------------------------------------------------------------------------
/src/ReactQuery_Mutation.ml:
--------------------------------------------------------------------------------
1 | type mutationContext
2 |
3 | type mutationStatus =
4 | [ `loading
5 | | `success
6 | | `error
7 | ]
8 |
9 | type ('mutationVariables, 'mutationData, 'mutationError, 'unknown) mutateParams = {
10 | onSuccess :
11 | ('mutationData ->
12 | 'mutationVariables ->
13 | mutationContext Js.Nullable.t ->
14 | 'unknown Js.Promise.t)
15 | option;
16 | onError :
17 | ('mutationError ->
18 | 'mutationVariables ->
19 | mutationContext Js.Nullable.t ->
20 | 'unknown Js.Promise.t)
21 | option;
22 | onSettled :
23 | ('mutationData ->
24 | 'mutationError ->
25 | 'mutationVariables ->
26 | mutationContext Js.Nullable.t ->
27 | 'unknown Js.Promise.t)
28 | option;
29 | }
30 |
31 | type ('mutationVariables, 'mutationData, 'mutationError, 'unknown) mutationOptions = {
32 | mutationKey : string array;
33 | mutationFn : 'mutationVariables -> 'mutationData Js.Promise.t;
34 | onMutate : ('mutationVariables -> mutationContext Js.Promise.t) option;
35 | onSuccess :
36 | ('mutationData ->
37 | 'mutationVariables ->
38 | mutationContext Js.Nullable.t ->
39 | 'unknown Js.Promise.t)
40 | option;
41 | onError :
42 | ('mutationError ->
43 | 'mutationVariables ->
44 | mutationContext Js.Nullable.t ->
45 | 'unknown Js.Promise.t)
46 | option;
47 | onSettled :
48 | ('mutationData ->
49 | 'mutationError ->
50 | 'mutationVariables ->
51 | mutationContext Js.Nullable.t ->
52 | 'unknown Js.Promise.t)
53 | option;
54 | retry : 'mutationError ReactQuery_Types.retryValue option;
55 | retryDelay : 'mutationError ReactQuery_Types.retryDelayValue option;
56 | useErrorBoundary : bool option;
57 | }
58 |
59 | let mutationOptions
60 | ?onMutate
61 | ?onSuccess
62 | ?onError
63 | ?onSettled
64 | ?retry
65 | ?retryDelay
66 | ?useErrorBoundary
67 | ~mutationKey
68 | ~mutationFn
69 | () =
70 | {
71 | mutationKey;
72 | mutationFn;
73 | onMutate;
74 | onSuccess;
75 | onError;
76 | onSettled;
77 | retry;
78 | retryDelay;
79 | useErrorBoundary;
80 | }
81 | ;;
82 |
83 | type ('mutationVariables, 'mutationData, 'mutationError, 'unknown) mutationResult = {
84 | mutate :
85 | ('mutationVariables ->
86 | ('mutationVariables, 'mutationData, 'mutationError, 'unknown) mutateParams option ->
87 | unit
88 | [@u]);
89 | mutateAsync :
90 | 'mutationVariables ->
91 | ('mutationVariables, 'mutationData, 'mutationError, 'unknown) mutateParams ->
92 | 'mutationData Js.Promise.t;
93 | status : mutationStatus;
94 | isIdle : bool;
95 | isError : bool;
96 | isLoading : bool;
97 | isSuccess : bool;
98 | data : 'mutationData option;
99 | error : 'mutationError Js.Nullable.t;
100 | reset : unit -> unit;
101 | }
102 |
103 | external useMutation :
104 | ('mutationVariables, 'mutationData, 'mutationError, 'unknown) mutationOptions ->
105 | ('mutationVariables, 'mutationData, 'mutationError, 'unknown) mutationResult
106 | = "useMutation"
107 | [@@module "@tanstack/react-query"]
108 |
--------------------------------------------------------------------------------
/src/ReactQuery_Query.ml:
--------------------------------------------------------------------------------
1 | type ('queryKey, 'queryData, 'queryError, 'pageParam) queryOptions = {
2 | queryKey : 'queryKey array option;
3 | queryFn :
4 | (('queryKey array, 'pageParam) ReactQuery_Types.queryFunctionContext ->
5 | 'queryData Js.Promise.t)
6 | option;
7 | enabled : bool option;
8 | retry : 'queryError ReactQuery_Types.retryValue option;
9 | retryOnMount : bool option;
10 | retryDelay : 'queryError ReactQuery_Types.retryDelayValue option;
11 | staleTime : ReactQuery_Types.timeValue option;
12 | queryKeyHashFn : ('queryKey array -> string) option;
13 | refetchInterval : ReactQuery_Types.refetchIntervalValue option;
14 | refetchIntervalInBackground : bool option;
15 | refetchOnMount : ReactQuery_Types.boolOrAlwaysValue option;
16 | refetchOnWindowFocus : ReactQuery_Types.boolOrAlwaysValue option;
17 | refetchOnReconnect : ReactQuery_Types.boolOrAlwaysValue option;
18 | notifyOnChangeProps : ReactQuery_Types.notifyOnChangePropsValue option;
19 | notifyOnChangePropsExclusions : string array option;
20 | onSuccess : ('queryData -> unit) option;
21 | onError : ('queryError -> unit) option;
22 | onSettled : ('queryData -> 'queryError -> unit) option;
23 | select : ('queryData -> 'queryData) option;
24 | suspense : bool option;
25 | keepPreviousData : bool option;
26 | structuralSharing : bool option;
27 | useErrorBoundary : bool option;
28 | initialData : ('queryData -> 'queryData) option;
29 | initialDataUpdatedAt : (unit -> int) option;
30 | placeholderData : (unit -> 'queryData) option;
31 | }
32 |
33 | let queryOptions
34 | ?queryKey
35 | ?queryFn
36 | ?enabled
37 | ?retry
38 | ?retryOnMount
39 | ?retryDelay
40 | ?staleTime
41 | ?queryKeyHashFn
42 | ?refetchInterval
43 | ?refetchIntervalInBackground
44 | ?refetchOnMount
45 | ?refetchOnWindowFocus
46 | ?refetchOnReconnect
47 | ?notifyOnChangeProps
48 | ?notifyOnChangePropsExclusions
49 | ?onSuccess
50 | ?onError
51 | ?onSettled
52 | ?select
53 | ?suspense
54 | ?keepPreviousData
55 | ?structuralSharing
56 | ?useErrorBoundary
57 | ?initialData
58 | ?initialDataUpdatedAt
59 | ?placeholderData
60 | () =
61 | {
62 | queryKey;
63 | queryFn;
64 | enabled;
65 | retry;
66 | retryOnMount;
67 | retryDelay;
68 | staleTime;
69 | queryKeyHashFn;
70 | refetchInterval;
71 | refetchIntervalInBackground;
72 | refetchOnMount;
73 | refetchOnWindowFocus;
74 | refetchOnReconnect;
75 | notifyOnChangeProps;
76 | notifyOnChangePropsExclusions;
77 | onSuccess;
78 | onError;
79 | onSettled;
80 | select;
81 | suspense;
82 | keepPreviousData;
83 | structuralSharing;
84 | useErrorBoundary;
85 | initialData;
86 | initialDataUpdatedAt;
87 | placeholderData;
88 | }
89 | ;;
90 |
91 | type ('queryError, 'queryData) queryResult = {
92 | status : ReactQuery_Types.queryStatus;
93 | isIdle : bool;
94 | isError : bool;
95 | isFetched : bool;
96 | isFetchedAfterMount : bool;
97 | isFetching : bool;
98 | isLoading : bool;
99 | isLoadingError : bool;
100 | isPlaceholderData : bool;
101 | isPreviousData : bool;
102 | isRefetchError : bool;
103 | isStale : bool;
104 | isSuccess : bool;
105 | data : 'queryData option;
106 | dataUpdatedAt : int;
107 | error : 'queryError Js.Nullable.t;
108 | errorUpdatedAt : int;
109 | failureCount : int;
110 | refetch :
111 | ReactQuery_Types.refetchOptions -> ('queryError, 'queryData) queryResult Js.Promise.t;
112 | remove : unit -> unit;
113 | }
114 |
115 | external useQuery :
116 | ('queryKey, 'queryData, 'queryError, 'pageParam) queryOptions ->
117 | ('queryError, 'queryData) queryResult
118 | = "useQuery"
119 | [@@module "@tanstack/react-query"]
120 |
121 | external useQueries :
122 | ('queryKey, 'queryData, 'queryError, 'pageParam) queryOptions array ->
123 | ('queryError, 'queryData) queryResult array
124 | = "useQueries"
125 | [@@module "@tanstack/react-query"]
126 |
--------------------------------------------------------------------------------
/src/ReactQuery_Types.ml:
--------------------------------------------------------------------------------
1 | type query
2 | type timeValue
3 | type boolOrAlwaysValue
4 | type refetchIntervalValue
5 | type notifyOnChangePropsValue
6 | type 'queryError retryValue
7 | type 'queryError retryDelayValue
8 | type 'queryKey queryDataKeyOrFilterValue
9 | type placeholderDataValue
10 |
11 | type ('queryKey, 'pageParam) queryFunctionContext = {
12 | queryKey : 'queryKey;
13 | pageParam : 'pageParam;
14 | }
15 |
16 | let queryFunctionContext ~queryKey ~pageParam = { queryKey; pageParam }
17 |
18 | type 'error retryParam =
19 | [ `bool of bool
20 | | `number of int
21 | | `fn of int -> 'error -> bool
22 | ]
23 |
24 | type 'error retryDelayParam =
25 | [ `number of int
26 | | `fn of int -> 'error -> int
27 | ]
28 |
29 | type time =
30 | [ `number of int
31 | | `infinity
32 | ]
33 |
34 | type refetchInterval =
35 | [ `bool of bool
36 | | `number of int
37 | ]
38 |
39 | type boolOrAlways =
40 | [ `bool of bool
41 | | `always
42 | ]
43 |
44 | type notifyOnChangeProps =
45 | [ `array of string array
46 | | `all
47 | ]
48 |
49 | type 'queryData infiniteData = {
50 | pages : 'queryData array;
51 | pageParams : int array;
52 | }
53 |
54 | let infiniteData ~pages ~pageParams = { pages; pageParams }
55 |
56 | type queryStatus =
57 | [ `loading
58 | | `success
59 | | `error
60 | | `initialData
61 | ]
62 |
63 | type ('queryData, 'queryResult) placeholderData =
64 | [ `data of 'queryData
65 | | `fn of unit -> 'queryResult option [@as "function"]
66 | ]
67 |
68 | type 'queryKey queryFilter = {
69 | exact : bool option;
70 | type_ : [ `active | `inactive | `all ] option; [@as "type"]
71 | stale : bool option;
72 | fetching : bool option;
73 | predicate : (query -> bool) option;
74 | queryKey : 'queryKey option;
75 | }
76 |
77 | let queryFilter ?exact ?type_ ?stale ?fetching ?predicate ?queryKey () =
78 | { exact; type_; stale; fetching; predicate; queryKey }
79 | ;;
80 |
81 | type 'queryKey queryDataKeyOrFilter =
82 | [ `keys of 'queryKey
83 | | `filters of 'queryKey queryFilter
84 | ]
85 |
86 | type refetchOptions = {
87 | throwOnError : bool;
88 | cancelRefetch : bool;
89 | }
90 |
91 | let refetchOptions ~throwOnError ~cancelRefetch = { throwOnError; cancelRefetch }
92 |
--------------------------------------------------------------------------------
/src/ReactQuery_Utils.ml:
--------------------------------------------------------------------------------
1 | let retry : 'error ReactQuery_Types.retryParam -> 'error ReactQuery_Types.retryValue =
2 | function
3 | | `bool value -> Obj.magic value
4 | | `number value -> Obj.magic value
5 | | `fn value -> Obj.magic value
6 | ;;
7 |
8 | let retryDelay :
9 | 'error ReactQuery_Types.retryDelayParam -> 'error ReactQuery_Types.retryDelayValue =
10 | function
11 | | `number value -> Obj.magic value
12 | | `fn value -> Obj.magic value
13 | ;;
14 |
15 | let time : ReactQuery_Types.time -> ReactQuery_Types.timeValue = function
16 | | `number value -> Obj.magic value
17 | | `infinity -> Obj.magic infinity
18 | ;;
19 |
20 | let refetchInterval = function
21 | | `bool value -> Obj.magic value
22 | | `number value -> Obj.magic value
23 | ;;
24 |
25 | let boolOrAlways = function
26 | | `bool value -> Obj.magic value
27 | | `always -> Obj.magic `always
28 | ;;
29 |
30 | let notifyOnChangeProps = function
31 | | `array value -> Obj.magic value
32 | | `tracked -> Obj.magic `tracked
33 | ;;
34 |
35 | let setQueryData :
36 | 'queryKey ReactQuery_Types.queryDataKeyOrFilter ->
37 | 'queryKey ReactQuery_Types.queryDataKeyOrFilter = function
38 | | `keys value -> Obj.magic value
39 | | `filters value -> Obj.magic value
40 | ;;
41 |
42 | let placeholderData :
43 | ('queryData, 'queryResult) ReactQuery_Types.placeholderData ->
44 | ReactQuery_Types.placeholderDataValue = function
45 | | `data data -> Obj.magic data
46 | | ((`fn value) [@as "function"]) -> Obj.magic value
47 | ;;
48 |
49 | let refetchOnMount = boolOrAlways
50 | let refetchOnWindowFocus = boolOrAlways
51 | let refetchOnReconnect = boolOrAlways
52 |
--------------------------------------------------------------------------------
/src/dune:
--------------------------------------------------------------------------------
1 | (library
2 | (name ReactQuery)
3 | (public_name melange-react-query)
4 | (libraries reason-react)
5 | (preprocess
6 | (pps melange.ppx reason-react-ppx))
7 | (modes melange))
8 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@tanstack/query-core@4.36.1":
6 | version "4.36.1"
7 | resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.36.1.tgz#79f8c1a539d47c83104210be2388813a7af2e524"
8 | integrity sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==
9 |
10 | "@tanstack/react-query@^4.2.1":
11 | version "4.36.1"
12 | resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.36.1.tgz#acb589fab4085060e2e78013164868c9c785e5d2"
13 | integrity sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==
14 | dependencies:
15 | "@tanstack/query-core" "4.36.1"
16 | use-sync-external-store "^1.2.0"
17 |
18 | "js-tokens@^3.0.0 || ^4.0.0":
19 | version "4.0.0"
20 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
21 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
22 |
23 | loose-envify@^1.1.0:
24 | version "1.4.0"
25 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
26 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
27 | dependencies:
28 | js-tokens "^3.0.0 || ^4.0.0"
29 |
30 | react-dom@^18.2.0:
31 | version "18.2.0"
32 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
33 | integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
34 | dependencies:
35 | loose-envify "^1.1.0"
36 | scheduler "^0.23.0"
37 |
38 | react@^18.2.0:
39 | version "18.2.0"
40 | resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
41 | integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
42 | dependencies:
43 | loose-envify "^1.1.0"
44 |
45 | scheduler@^0.23.0:
46 | version "0.23.0"
47 | resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
48 | integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
49 | dependencies:
50 | loose-envify "^1.1.0"
51 |
52 | use-sync-external-store@^1.2.0:
53 | version "1.2.0"
54 | resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
55 | integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
56 |
--------------------------------------------------------------------------------