@comapeo/core-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ import { useSuspenseQuery } from '@tanstack/react-query';
2
+ import { documentByDocumentIdQueryOptions, documentByVersionIdQueryOptions, documentsQueryOptions, } from '../lib/react-query/documents';
3
+ import { useSingleProject } from './projects';
4
+ // TODO: Return type is not narrowed properly by `docType`
5
+ /**
6
+ * Retrieve a single document from the database based on the document's document ID.
7
+ *
8
+ * Triggers the closest error boundary if the document cannot be found
9
+ *
10
+ * @param {Object} opts
11
+ * @param {string} opts.projectId Project public ID
12
+ * @param {DocumentType} opts.docType Document type of interest
13
+ * @param {string} opts.docId Document ID
14
+ * @param {Object} [opts.opts]
15
+ * @param {string} [opts.opts.lang] Language to translate the document into
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * function SingleDocumentByDocIdExample() {
20
+ * const { data } = useSingleDocByDocId({
21
+ * projectId: '...',
22
+ * docType: 'observation',
23
+ * docId: '...',
24
+ * })
25
+ *
26
+ * console.log(data.schemaName) // logs 'observation'
27
+ * }
28
+ * ```
29
+ */
30
+ export function useSingleDocByDocId({ projectId, docType, docId, opts, }) {
31
+ const { data: projectApi } = useSingleProject({ projectId });
32
+ const { data, error, isRefetching } = useSuspenseQuery(documentByDocumentIdQueryOptions({
33
+ projectApi,
34
+ projectId,
35
+ docType,
36
+ docId,
37
+ opts,
38
+ }));
39
+ return { data, error, isRefetching };
40
+ }
41
+ // TODO: Return type is not narrowed properly by `docType`
42
+ /**
43
+ * Retrieve a single document from the database based on the document's version ID.
44
+ *
45
+ * Triggers the closest error boundary if the document cannot be found.
46
+ *
47
+ * @param {Object} opts
48
+ * @param {string} opts.projectId Project public ID
49
+ * @param {DocumentType} opts.docType Document type of interest
50
+ * @param {string} opts.versionId Document's version ID
51
+ * @param {Object} [opts.opts]
52
+ * @param {string} [opts.opts.lang] Language to translate the document into
53
+ *
54
+ * * @example
55
+ * ```tsx
56
+ * function SingleDocumentByVersionIdExample() {
57
+ * const { data } = useSingleDocByVersionId({
58
+ * projectId: '...',
59
+ * docType: 'observation',
60
+ * docId: '...',
61
+ * })
62
+ *
63
+ * console.log(data.schemaName) // logs 'observation'
64
+ * }
65
+ * ```
66
+ */
67
+ export function useSingleDocByVersionId({ projectId, docType, versionId, opts, }) {
68
+ const { data: projectApi } = useSingleProject({ projectId });
69
+ const { data, error, isRefetching } = useSuspenseQuery(documentByVersionIdQueryOptions({
70
+ projectApi,
71
+ projectId,
72
+ docType,
73
+ versionId,
74
+ opts,
75
+ }));
76
+ return { data, error, isRefetching };
77
+ }
78
+ // TODO: Return type is not narrowed properly by `docType`
79
+ /**
80
+ * Retrieve all documents of a specific `docType`.
81
+ *
82
+ * @param {Object} opts
83
+ * @param {string} opts.projectId Project public ID
84
+ * @param {DocumentType} opts.docType Document type of interest
85
+ * @param {Object} [opts.opts]
86
+ * @param {boolean} [opts.opts.includeDeleted] Include documents that have been marked as deleted
87
+ * @param {string} [opts.opts.lang] Language to translate the documents into
88
+ *
89
+ * @example
90
+ * ```tsx
91
+ * function BasicExample() {
92
+ * const { data } = useManyDocs({
93
+ * projectId: '...',
94
+ * docType: 'observations',
95
+ * })
96
+ * }
97
+ * ```
98
+ *
99
+ * ```tsx
100
+ * function useAllObservations(opts) {
101
+ * return useManyDocs({
102
+ * ...opts,
103
+ * docType: 'observations',
104
+ * })
105
+ * }
106
+ *
107
+ * function useAllPresets(opts) {
108
+ * return useManyDocs({
109
+ * ...opts,
110
+ * docType: 'presets',
111
+ * })
112
+ * }
113
+ * ```
114
+ */
115
+ export function useManyDocs({ projectId, docType, opts, }) {
116
+ const { data: projectApi } = useSingleProject({ projectId });
117
+ const { data, error, isRefetching } = useSuspenseQuery(documentsQueryOptions({
118
+ projectApi,
119
+ projectId,
120
+ docType,
121
+ opts,
122
+ }));
123
+ return { data, error, isRefetching };
124
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Get a URL that points to a StyleJSON resource served by the embedded HTTP server.
3
+ *
4
+ * If `opts.refreshToken` is specified, it will be appended to the returned URL as a search param. This is useful for forcing cache busting
5
+ * due to hidden internal details by consuming components (e.g. map component from MapLibre).
6
+ *
7
+ * @param {Object} opts
8
+ * @param {string} opts.refreshToken String to append to the returned value as a search param
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * function ExampleWithoutRefreshToken() {
13
+ * const { data, isRefetching } = useMapStyleUrl()
14
+ *
15
+ * console.log(data) // logs something like 'http://localhost:...'
16
+ * }
17
+ * ```
18
+ *
19
+ * ```tsx
20
+ * function ExampleWithRefreshToken() {
21
+ * const [refreshToken] = useState('foo')
22
+ * const { data } = useMapStyleUrl({ refreshToken })
23
+ *
24
+ * console.log(data) // logs something like 'http://localhost:...?refresh_token=foo'
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function useMapStyleUrl({ refreshToken, }?: {
29
+ refreshToken?: string;
30
+ }): {
31
+ data: string;
32
+ error: Error | null;
33
+ isRefetching: boolean;
34
+ };
@@ -0,0 +1,35 @@
1
+ import { useSuspenseQuery } from '@tanstack/react-query';
2
+ import { mapStyleJsonUrlQueryOptions } from '../lib/react-query/maps';
3
+ import { useClientApi } from './client';
4
+ /**
5
+ * Get a URL that points to a StyleJSON resource served by the embedded HTTP server.
6
+ *
7
+ * If `opts.refreshToken` is specified, it will be appended to the returned URL as a search param. This is useful for forcing cache busting
8
+ * due to hidden internal details by consuming components (e.g. map component from MapLibre).
9
+ *
10
+ * @param {Object} opts
11
+ * @param {string} opts.refreshToken String to append to the returned value as a search param
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * function ExampleWithoutRefreshToken() {
16
+ * const { data, isRefetching } = useMapStyleUrl()
17
+ *
18
+ * console.log(data) // logs something like 'http://localhost:...'
19
+ * }
20
+ * ```
21
+ *
22
+ * ```tsx
23
+ * function ExampleWithRefreshToken() {
24
+ * const [refreshToken] = useState('foo')
25
+ * const { data } = useMapStyleUrl({ refreshToken })
26
+ *
27
+ * console.log(data) // logs something like 'http://localhost:...?refresh_token=foo'
28
+ * }
29
+ * ```
30
+ */
31
+ export function useMapStyleUrl({ refreshToken, } = {}) {
32
+ const clientApi = useClientApi();
33
+ const { data, error, isRefetching } = useSuspenseQuery(mapStyleJsonUrlQueryOptions({ clientApi, refreshToken }));
34
+ return { data, error, isRefetching };
35
+ }
@@ -0,0 +1,261 @@
1
+ import type { BlobId } from '@comapeo/core/dist/types';
2
+ import { iconUrlQueryOptions } from '../lib/react-query/projects';
3
+ /**
4
+ * Retrieve the project settings for a project.
5
+ *
6
+ * @param {Object} opts
7
+ * @param {string} opts.projectId Project public ID
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * function BasicExample() {
12
+ * const { data } = useProjectSettings({ projectId: '...' })
13
+ *
14
+ * console.log(data.name)
15
+ * }
16
+ * ```
17
+ */
18
+ export declare function useProjectSettings({ projectId }: {
19
+ projectId: string;
20
+ }): {
21
+ data: import("@comapeo/core/dist/mapeo-project").EditableProjectSettings;
22
+ error: Error | null;
23
+ isRefetching: boolean;
24
+ };
25
+ /**
26
+ * Retrieve a project API instance for a project.
27
+ *
28
+ * This is mostly used internally by the other hooks and should only be used if certain project APIs are not exposed via the hooks.
29
+ *
30
+ * @param {Object} opts
31
+ * @param {string} opts.projectId Project public ID
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * function BasicExample() {
36
+ * const { data } = useSingleProject({ projectId: '...' })
37
+ * }
38
+ * ```
39
+ */
40
+ export declare function useSingleProject({ projectId }: {
41
+ projectId: string;
42
+ }): {
43
+ data: import("rpc-reflector/lib/types").ClientApi<import("@comapeo/core/dist/mapeo-project").MapeoProject>;
44
+ error: Error | null;
45
+ isRefetching: boolean;
46
+ };
47
+ /**
48
+ * Retrieve project information for each project that exists.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * function BasicExample() {
53
+ * const { data } = useManyProjects()
54
+ *
55
+ * console.log(data.map(project => project.name))
56
+ * }
57
+ * ```
58
+ */
59
+ export declare function useManyProjects(): {
60
+ data: (Pick<{
61
+ schemaName: "projectSettings";
62
+ name?: string | undefined;
63
+ defaultPresets?: {
64
+ point: string[];
65
+ area: string[];
66
+ vertex: string[];
67
+ line: string[];
68
+ relation: string[];
69
+ } | undefined;
70
+ configMetadata?: {
71
+ name: string;
72
+ buildDate: string;
73
+ importDate: string;
74
+ fileVersion: string;
75
+ } | undefined;
76
+ }, "name"> & {
77
+ projectId: string;
78
+ createdAt?: string | undefined;
79
+ updatedAt?: string | undefined;
80
+ })[];
81
+ error: Error | null;
82
+ isRefetching: boolean;
83
+ };
84
+ /**
85
+ * Retrieve a single member of a project.
86
+ *
87
+ * @param {Object} opts
88
+ * @param {string} opts.projectId Project public ID
89
+ * @param {deviceId} opts.projectId Device ID of interest
90
+ *
91
+ * @example
92
+ * ```tsx
93
+ * function BasicExample() {
94
+ * const { data } = useSingleMember({ projectId: '...', deviceId: '...' })
95
+ *
96
+ * console.log(data.role)
97
+ * }
98
+ * ```
99
+ */
100
+ export declare function useSingleMember({ projectId, deviceId, }: {
101
+ projectId: string;
102
+ deviceId: string;
103
+ }): {
104
+ data: import("@comapeo/core/dist/member-api").MemberInfo;
105
+ error: Error | null;
106
+ isRefetching: boolean;
107
+ };
108
+ /**
109
+ * Retrieve all members of a project.
110
+ *
111
+ * @param {Object} opts
112
+ * @param {string} opts.projectId Project public ID
113
+ *
114
+ * @example
115
+ * ```tsx
116
+ * function BasicExample() {
117
+ * const { data } = useManyMembers({ projectId: '...' })
118
+ *
119
+ * console.log(data.role)
120
+ * }
121
+ * ```
122
+ */
123
+ export declare function useManyMembers({ projectId }: {
124
+ projectId: string;
125
+ }): {
126
+ data: import("@comapeo/core/dist/member-api").MemberInfo[];
127
+ error: Error | null;
128
+ isRefetching: boolean;
129
+ };
130
+ /**
131
+ * Retrieve a URL that points to icon resources served by the embedded HTTP server.
132
+ *
133
+ * _TODO: Explain bitmap opts vs svg opts_
134
+ *
135
+ * @param {Object} opts
136
+ * @param {string} opts.projectId Project public ID
137
+ * @param {string} opts.iconId Icon ID of interest
138
+ * @param {BitmapOpts | SvgOpts} opts.opts Parameters related to the mime type of the icon of interest
139
+ *
140
+ * @example
141
+ * ```tsx
142
+ * function PngExample() {
143
+ * const { data } = useIconUrl({
144
+ * projectId: '...',
145
+ * iconId: '...',
146
+ * opts: {
147
+ * mimeType: 'image/png',
148
+ * pixelDensity: 1,
149
+ * size: 'medium'
150
+ * }
151
+ * })
152
+ * }
153
+ * ```
154
+ *
155
+ * ```tsx
156
+ * function SvgExample() {
157
+ * const { data } = useIconUrl({
158
+ * projectId: '...',
159
+ * iconId: '...',
160
+ * opts: {
161
+ * mimeType: 'image/svg',
162
+ * size: 'medium'
163
+ * }
164
+ * })
165
+ * }
166
+ * ```
167
+ */
168
+ export declare function useIconUrl({ projectId, iconId, opts, }: {
169
+ projectId: string;
170
+ iconId: string;
171
+ opts: Parameters<typeof iconUrlQueryOptions>[0]['opts'];
172
+ }): {
173
+ data: string;
174
+ error: Error | null;
175
+ isRefetching: boolean;
176
+ };
177
+ /**
178
+ * Retrieve a URL that points to a desired blob resource.
179
+ *
180
+ * _TODO: Explain BlobId in more depth_
181
+ *
182
+ * @param {Object} opts
183
+ * @param {string} opts.projectId Project public Id
184
+ * @param {BlobId} opts.blobId Blob ID of the desired resource
185
+ *
186
+ * @example
187
+ * ```tsx
188
+ * function PhotoExample() {
189
+ * const { data } = useAttachmentUrl({
190
+ * projectId: '...',
191
+ * blobId: {
192
+ * type: 'photo',
193
+ * variant: 'thumbnail',
194
+ * name: '...',
195
+ * driveId: '...',
196
+ * }
197
+ * })
198
+ * }
199
+ * ```
200
+ *
201
+ * ```tsx
202
+ * function AudioExample() {
203
+ * const { data } = useAttachmentUrl({
204
+ * projectId: '...',
205
+ * blobId: {
206
+ * type: 'audio',
207
+ * variant: 'original',
208
+ * name: '...',
209
+ * driveId: '...',
210
+ * }
211
+ * })
212
+ * }
213
+ * ```
214
+ *
215
+ * ```tsx
216
+ * function VideoExample() {
217
+ * const { data } = useAttachmentUrl({
218
+ * projectId: '...',
219
+ * blobId: {
220
+ * type: 'video',
221
+ * variant: 'original',
222
+ * name: '...',
223
+ * driveId: '...',
224
+ * }
225
+ * })
226
+ * }
227
+ * ```
228
+ */
229
+ export declare function useAttachmentUrl({ projectId, blobId, }: {
230
+ projectId: string;
231
+ blobId: BlobId;
232
+ }): {
233
+ data: string;
234
+ error: Error | null;
235
+ isRefetching: boolean;
236
+ };
237
+ /**
238
+ * Retrieve the device ID that created a document.
239
+ *
240
+ * @param {Object} opts
241
+ * @param {string} opts.projectId Project public ID
242
+ * @param {string} opts.originalVersionId Version ID of document
243
+ *
244
+ * @example
245
+ * ```tsx
246
+ * function BasicExample() {
247
+ * const { data } = useDocumentCreatedBy({
248
+ * projectId: '...',
249
+ * originalVersionId: '...',
250
+ * })
251
+ * }
252
+ * ```
253
+ */
254
+ export declare function useDocumentCreatedBy({ projectId, originalVersionId, }: {
255
+ projectId: string;
256
+ originalVersionId: string;
257
+ }): {
258
+ data: string;
259
+ error: Error | null;
260
+ isRefetching: boolean;
261
+ };
@@ -0,0 +1,257 @@
1
+ import { useSuspenseQuery } from '@tanstack/react-query';
2
+ import { attachmentUrlQueryOptions, documentCreatedByQueryOptions, iconUrlQueryOptions, projectByIdQueryOptions, projectMemberByIdQueryOptions, projectMembersQueryOptions, projectSettingsQueryOptions, projectsQueryOptions, } from '../lib/react-query/projects';
3
+ import { useClientApi } from './client';
4
+ /**
5
+ * Retrieve the project settings for a project.
6
+ *
7
+ * @param {Object} opts
8
+ * @param {string} opts.projectId Project public ID
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * function BasicExample() {
13
+ * const { data } = useProjectSettings({ projectId: '...' })
14
+ *
15
+ * console.log(data.name)
16
+ * }
17
+ * ```
18
+ */
19
+ export function useProjectSettings({ projectId }) {
20
+ const clientApi = useClientApi();
21
+ const { data: projectApi } = useSuspenseQuery(projectByIdQueryOptions({
22
+ projectId,
23
+ clientApi,
24
+ }));
25
+ const { data, error, isRefetching } = useSuspenseQuery(projectSettingsQueryOptions({
26
+ projectApi,
27
+ projectId,
28
+ }));
29
+ return { data, error, isRefetching };
30
+ }
31
+ /**
32
+ * Retrieve a project API instance for a project.
33
+ *
34
+ * This is mostly used internally by the other hooks and should only be used if certain project APIs are not exposed via the hooks.
35
+ *
36
+ * @param {Object} opts
37
+ * @param {string} opts.projectId Project public ID
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * function BasicExample() {
42
+ * const { data } = useSingleProject({ projectId: '...' })
43
+ * }
44
+ * ```
45
+ */
46
+ export function useSingleProject({ projectId }) {
47
+ const clientApi = useClientApi();
48
+ const { data, error, isRefetching } = useSuspenseQuery({
49
+ ...projectByIdQueryOptions({
50
+ clientApi,
51
+ projectId,
52
+ }),
53
+ // Keep project instances around indefinitely - shouldn't be a memory
54
+ // problem because these are only lightweight proxy objects, and project
55
+ // references are kept indefinitely on the backend anyway once they are
56
+ // accessed
57
+ staleTime: Infinity,
58
+ gcTime: Infinity,
59
+ });
60
+ return { data, error, isRefetching };
61
+ }
62
+ /**
63
+ * Retrieve project information for each project that exists.
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * function BasicExample() {
68
+ * const { data } = useManyProjects()
69
+ *
70
+ * console.log(data.map(project => project.name))
71
+ * }
72
+ * ```
73
+ */
74
+ export function useManyProjects() {
75
+ const clientApi = useClientApi();
76
+ const { data, error, isRefetching } = useSuspenseQuery(projectsQueryOptions({
77
+ clientApi,
78
+ }));
79
+ return { data, error, isRefetching };
80
+ }
81
+ /**
82
+ * Retrieve a single member of a project.
83
+ *
84
+ * @param {Object} opts
85
+ * @param {string} opts.projectId Project public ID
86
+ * @param {deviceId} opts.projectId Device ID of interest
87
+ *
88
+ * @example
89
+ * ```tsx
90
+ * function BasicExample() {
91
+ * const { data } = useSingleMember({ projectId: '...', deviceId: '...' })
92
+ *
93
+ * console.log(data.role)
94
+ * }
95
+ * ```
96
+ */
97
+ export function useSingleMember({ projectId, deviceId, }) {
98
+ const { data: projectApi } = useSingleProject({ projectId });
99
+ const { data, error, isRefetching } = useSuspenseQuery(projectMemberByIdQueryOptions({
100
+ projectApi,
101
+ projectId,
102
+ deviceId,
103
+ }));
104
+ return { data, error, isRefetching };
105
+ }
106
+ /**
107
+ * Retrieve all members of a project.
108
+ *
109
+ * @param {Object} opts
110
+ * @param {string} opts.projectId Project public ID
111
+ *
112
+ * @example
113
+ * ```tsx
114
+ * function BasicExample() {
115
+ * const { data } = useManyMembers({ projectId: '...' })
116
+ *
117
+ * console.log(data.role)
118
+ * }
119
+ * ```
120
+ */
121
+ export function useManyMembers({ projectId }) {
122
+ const { data: projectApi } = useSingleProject({ projectId });
123
+ const { data, error, isRefetching } = useSuspenseQuery(projectMembersQueryOptions({ projectApi, projectId }));
124
+ return { data, error, isRefetching };
125
+ }
126
+ /**
127
+ * Retrieve a URL that points to icon resources served by the embedded HTTP server.
128
+ *
129
+ * _TODO: Explain bitmap opts vs svg opts_
130
+ *
131
+ * @param {Object} opts
132
+ * @param {string} opts.projectId Project public ID
133
+ * @param {string} opts.iconId Icon ID of interest
134
+ * @param {BitmapOpts | SvgOpts} opts.opts Parameters related to the mime type of the icon of interest
135
+ *
136
+ * @example
137
+ * ```tsx
138
+ * function PngExample() {
139
+ * const { data } = useIconUrl({
140
+ * projectId: '...',
141
+ * iconId: '...',
142
+ * opts: {
143
+ * mimeType: 'image/png',
144
+ * pixelDensity: 1,
145
+ * size: 'medium'
146
+ * }
147
+ * })
148
+ * }
149
+ * ```
150
+ *
151
+ * ```tsx
152
+ * function SvgExample() {
153
+ * const { data } = useIconUrl({
154
+ * projectId: '...',
155
+ * iconId: '...',
156
+ * opts: {
157
+ * mimeType: 'image/svg',
158
+ * size: 'medium'
159
+ * }
160
+ * })
161
+ * }
162
+ * ```
163
+ */
164
+ export function useIconUrl({ projectId, iconId, opts, }) {
165
+ const { data: projectApi } = useSingleProject({ projectId });
166
+ const { data, error, isRefetching } = useSuspenseQuery(iconUrlQueryOptions({
167
+ projectApi,
168
+ projectId,
169
+ iconId,
170
+ opts,
171
+ }));
172
+ return { data, error, isRefetching };
173
+ }
174
+ /**
175
+ * Retrieve a URL that points to a desired blob resource.
176
+ *
177
+ * _TODO: Explain BlobId in more depth_
178
+ *
179
+ * @param {Object} opts
180
+ * @param {string} opts.projectId Project public Id
181
+ * @param {BlobId} opts.blobId Blob ID of the desired resource
182
+ *
183
+ * @example
184
+ * ```tsx
185
+ * function PhotoExample() {
186
+ * const { data } = useAttachmentUrl({
187
+ * projectId: '...',
188
+ * blobId: {
189
+ * type: 'photo',
190
+ * variant: 'thumbnail',
191
+ * name: '...',
192
+ * driveId: '...',
193
+ * }
194
+ * })
195
+ * }
196
+ * ```
197
+ *
198
+ * ```tsx
199
+ * function AudioExample() {
200
+ * const { data } = useAttachmentUrl({
201
+ * projectId: '...',
202
+ * blobId: {
203
+ * type: 'audio',
204
+ * variant: 'original',
205
+ * name: '...',
206
+ * driveId: '...',
207
+ * }
208
+ * })
209
+ * }
210
+ * ```
211
+ *
212
+ * ```tsx
213
+ * function VideoExample() {
214
+ * const { data } = useAttachmentUrl({
215
+ * projectId: '...',
216
+ * blobId: {
217
+ * type: 'video',
218
+ * variant: 'original',
219
+ * name: '...',
220
+ * driveId: '...',
221
+ * }
222
+ * })
223
+ * }
224
+ * ```
225
+ */
226
+ export function useAttachmentUrl({ projectId, blobId, }) {
227
+ const { data: projectApi } = useSingleProject({ projectId });
228
+ const { data, error, isRefetching } = useSuspenseQuery(attachmentUrlQueryOptions({
229
+ projectApi,
230
+ projectId,
231
+ blobId,
232
+ }));
233
+ return { data, error, isRefetching };
234
+ }
235
+ // TODO: Eventually remove in favor of this information being provided by the backend when retrieving documents
236
+ /**
237
+ * Retrieve the device ID that created a document.
238
+ *
239
+ * @param {Object} opts
240
+ * @param {string} opts.projectId Project public ID
241
+ * @param {string} opts.originalVersionId Version ID of document
242
+ *
243
+ * @example
244
+ * ```tsx
245
+ * function BasicExample() {
246
+ * const { data } = useDocumentCreatedBy({
247
+ * projectId: '...',
248
+ * originalVersionId: '...',
249
+ * })
250
+ * }
251
+ * ```
252
+ */
253
+ export function useDocumentCreatedBy({ projectId, originalVersionId, }) {
254
+ const { data: projectApi } = useSingleProject({ projectId });
255
+ const { data, error, isRefetching } = useSuspenseQuery(documentCreatedByQueryOptions({ projectApi, projectId, originalVersionId }));
256
+ return { data, error, isRefetching };
257
+ }