@pylo/react 0.7.0 → 0.8.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,540 @@
1
+ import {
2
+ usePyloTransport
3
+ } from "./chunk-3WSGP2SO.js";
4
+
5
+ // src/hooks.ts
6
+ import { useCallback, useRef, useState } from "react";
7
+ import {
8
+ useQuery,
9
+ useInfiniteQuery,
10
+ useMutation,
11
+ useQueryClient
12
+ } from "@tanstack/react-query";
13
+ import {
14
+ buildListQuery,
15
+ buildByIdQuery,
16
+ buildMeQuery,
17
+ mergeHeaders,
18
+ flagsToHeaders,
19
+ capitalize,
20
+ toAggregateResult
21
+ } from "@pylo/core";
22
+ import {
23
+ buildUpsertMutation,
24
+ buildBulkUpsertMutation,
25
+ buildDeleteMutation,
26
+ buildIngestEventsMutation,
27
+ buildEntityAggregateQuery,
28
+ buildEventAggregateQuery,
29
+ buildEventListQuery,
30
+ buildEventPropertyKeysQuery,
31
+ buildEventFieldValuesQuery
32
+ } from "@pylo/core";
33
+ import {
34
+ CREATE_UPLOAD_MUTATION,
35
+ CREATE_DOWNLOAD_MUTATION,
36
+ buildCreateUploadInput,
37
+ buildAttachMutation,
38
+ uploadToUrl,
39
+ toUploadPart
40
+ } from "@pylo/core";
41
+ function createPyloHooks(options) {
42
+ var _a;
43
+ const useTransport = (_a = options == null ? void 0 : options.useTransport) != null ? _a : usePyloTransport;
44
+ const globalHeaders = options == null ? void 0 : options.headers;
45
+ function usePyloList(entity, queryOptions) {
46
+ var _a2, _b, _c;
47
+ const transport = useTransport();
48
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
49
+ const queryKey = [
50
+ "pylo",
51
+ entity,
52
+ "list",
53
+ {
54
+ filter: queryOptions == null ? void 0 : queryOptions.filter,
55
+ pagination: queryOptions == null ? void 0 : queryOptions.pagination,
56
+ select: queryOptions == null ? void 0 : queryOptions.select,
57
+ headers: merged
58
+ }
59
+ ];
60
+ const result = useQuery({
61
+ queryKey,
62
+ queryFn: async () => {
63
+ const { query, variables } = buildListQuery(
64
+ entity,
65
+ queryOptions
66
+ );
67
+ const data = await transport(query, variables, merged);
68
+ const listKey = `${entity}List`;
69
+ return data[listKey];
70
+ }
71
+ });
72
+ return {
73
+ data: (_b = (_a2 = result.data) == null ? void 0 : _a2.data) != null ? _b : void 0,
74
+ pagination: (_c = result.data) == null ? void 0 : _c.pagination,
75
+ isLoading: result.isLoading,
76
+ error: result.error,
77
+ refetch: result.refetch
78
+ };
79
+ }
80
+ function usePyloInfiniteList(entity, infiniteOptions) {
81
+ var _a2;
82
+ const transport = useTransport();
83
+ const perPage = (_a2 = infiniteOptions == null ? void 0 : infiniteOptions.perPage) != null ? _a2 : 20;
84
+ const merged = mergeHeaders(globalHeaders, infiniteOptions == null ? void 0 : infiniteOptions.headers);
85
+ return useInfiniteQuery({
86
+ queryKey: [
87
+ "pylo",
88
+ entity,
89
+ "infiniteList",
90
+ {
91
+ perPage,
92
+ filter: infiniteOptions == null ? void 0 : infiniteOptions.filter,
93
+ select: infiniteOptions == null ? void 0 : infiniteOptions.select,
94
+ headers: merged
95
+ }
96
+ ],
97
+ queryFn: async ({ pageParam }) => {
98
+ const runtimeOptions = {
99
+ select: infiniteOptions == null ? void 0 : infiniteOptions.select,
100
+ filter: infiniteOptions == null ? void 0 : infiniteOptions.filter,
101
+ pagination: { page: pageParam, per_page: perPage }
102
+ };
103
+ const { query, variables } = buildListQuery(
104
+ entity,
105
+ runtimeOptions
106
+ );
107
+ const data = await transport(query, variables, merged);
108
+ const listKey = `${entity}List`;
109
+ return data[listKey];
110
+ },
111
+ initialPageParam: 1,
112
+ getNextPageParam: (lastPage) => {
113
+ if (lastPage.pagination.has_more_pages) {
114
+ return lastPage.pagination.current_page + 1;
115
+ }
116
+ return void 0;
117
+ },
118
+ select: (queryData) => {
119
+ const allData = queryData.pages.flatMap(
120
+ (page) => page.data
121
+ );
122
+ return {
123
+ ...queryData,
124
+ data: allData,
125
+ pages: queryData.pages
126
+ };
127
+ }
128
+ });
129
+ }
130
+ function usePyloById(entity, id, queryOptions) {
131
+ const transport = useTransport();
132
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
133
+ return useQuery({
134
+ queryKey: ["pylo", entity, "byId", id, { select: queryOptions == null ? void 0 : queryOptions.select, headers: merged }],
135
+ queryFn: async () => {
136
+ const { query, variables } = buildByIdQuery(
137
+ entity,
138
+ id,
139
+ queryOptions
140
+ );
141
+ const data = await transport(query, variables, merged);
142
+ const byIdKey = `${entity}ById`;
143
+ const result = data[byIdKey];
144
+ if (!result) return null;
145
+ return result.data;
146
+ },
147
+ enabled: !!id
148
+ });
149
+ }
150
+ function usePyloMe(queryOptions) {
151
+ const transport = useTransport();
152
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
153
+ return useQuery({
154
+ queryKey: ["pylo", "me", { select: queryOptions == null ? void 0 : queryOptions.select, headers: merged }],
155
+ queryFn: async () => {
156
+ const { query, variables } = buildMeQuery(
157
+ queryOptions
158
+ );
159
+ const data = await transport(query, variables, merged);
160
+ return data["me"];
161
+ }
162
+ });
163
+ }
164
+ function usePyloAggregate(entity, queryOptions) {
165
+ const transport = useTransport();
166
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
167
+ return useQuery({
168
+ queryKey: [
169
+ "pylo",
170
+ entity,
171
+ "aggregate",
172
+ {
173
+ metrics: queryOptions == null ? void 0 : queryOptions.metrics,
174
+ groupBy: queryOptions == null ? void 0 : queryOptions.groupBy,
175
+ filter: queryOptions == null ? void 0 : queryOptions.filter,
176
+ limit: queryOptions == null ? void 0 : queryOptions.limit,
177
+ headers: merged
178
+ }
179
+ ],
180
+ queryFn: async () => {
181
+ const { query, variables } = buildEntityAggregateQuery(
182
+ capitalize(entity),
183
+ queryOptions
184
+ );
185
+ const data = await transport(query, variables, merged);
186
+ const result = data["entityInstanceAggregate"];
187
+ return toAggregateResult(
188
+ result.rows,
189
+ result.total,
190
+ queryOptions
191
+ );
192
+ }
193
+ });
194
+ }
195
+ function usePyloEventAggregate(queryOptions) {
196
+ const transport = useTransport();
197
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
198
+ return useQuery({
199
+ queryKey: [
200
+ "pylo",
201
+ "events",
202
+ "aggregate",
203
+ {
204
+ metrics: queryOptions == null ? void 0 : queryOptions.metrics,
205
+ groupBy: queryOptions == null ? void 0 : queryOptions.groupBy,
206
+ filter: queryOptions == null ? void 0 : queryOptions.filter,
207
+ limit: queryOptions == null ? void 0 : queryOptions.limit,
208
+ startTime: queryOptions == null ? void 0 : queryOptions.startTime,
209
+ headers: merged
210
+ }
211
+ ],
212
+ queryFn: async () => {
213
+ const { query, variables } = buildEventAggregateQuery(
214
+ queryOptions
215
+ );
216
+ const data = await transport(query, variables, merged);
217
+ const result = data["pyloEventList"];
218
+ return toAggregateResult(
219
+ result.data,
220
+ result.aggregations,
221
+ queryOptions
222
+ );
223
+ }
224
+ });
225
+ }
226
+ function usePyloUpsert(entity, mutationOptions) {
227
+ const transport = useTransport();
228
+ const queryClient = useQueryClient();
229
+ const merged = mergeHeaders(
230
+ mergeHeaders(globalHeaders, mutationOptions == null ? void 0 : mutationOptions.headers),
231
+ flagsToHeaders(mutationOptions != null ? mutationOptions : {})
232
+ );
233
+ const isDryRun = (mutationOptions == null ? void 0 : mutationOptions.dryRun) === true;
234
+ return useMutation({
235
+ ...mutationOptions,
236
+ mutationFn: async (input) => {
237
+ const pascalName = capitalize(entity);
238
+ const { query, variables, field } = buildUpsertMutation(
239
+ entity,
240
+ pascalName,
241
+ input
242
+ );
243
+ const data = await transport(query, variables, merged);
244
+ return data[field].data;
245
+ },
246
+ onSuccess: (data, variables, onMutateResult, context) => {
247
+ var _a2;
248
+ if (!isDryRun) {
249
+ void queryClient.invalidateQueries({
250
+ queryKey: ["pylo", entity]
251
+ });
252
+ }
253
+ (_a2 = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a2.call(mutationOptions, data, variables, onMutateResult, context);
254
+ }
255
+ });
256
+ }
257
+ function usePyloBulkUpsert(entity, mutationOptions) {
258
+ const transport = useTransport();
259
+ const queryClient = useQueryClient();
260
+ const merged = mergeHeaders(
261
+ mergeHeaders(globalHeaders, mutationOptions == null ? void 0 : mutationOptions.headers),
262
+ flagsToHeaders(mutationOptions != null ? mutationOptions : {})
263
+ );
264
+ const isDryRun = (mutationOptions == null ? void 0 : mutationOptions.dryRun) === true;
265
+ return useMutation({
266
+ ...mutationOptions,
267
+ mutationFn: async (inputs) => {
268
+ const pascalName = capitalize(entity);
269
+ const { query, variables, field } = buildBulkUpsertMutation(
270
+ entity,
271
+ pascalName,
272
+ inputs
273
+ );
274
+ const data = await transport(query, variables, merged);
275
+ return data[field].data;
276
+ },
277
+ onSuccess: (data, variables, onMutateResult, context) => {
278
+ var _a2;
279
+ if (!isDryRun) {
280
+ void queryClient.invalidateQueries({
281
+ queryKey: ["pylo", entity]
282
+ });
283
+ }
284
+ (_a2 = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a2.call(mutationOptions, data, variables, onMutateResult, context);
285
+ }
286
+ });
287
+ }
288
+ function usePyloDelete(entity, mutationOptions) {
289
+ const transport = useTransport();
290
+ const queryClient = useQueryClient();
291
+ const merged = mergeHeaders(
292
+ mergeHeaders(globalHeaders, mutationOptions == null ? void 0 : mutationOptions.headers),
293
+ flagsToHeaders(mutationOptions != null ? mutationOptions : {})
294
+ );
295
+ const isDryRun = (mutationOptions == null ? void 0 : mutationOptions.dryRun) === true;
296
+ return useMutation({
297
+ ...mutationOptions,
298
+ mutationFn: async (ids) => {
299
+ const pascalName = capitalize(entity);
300
+ const { query, variables } = buildDeleteMutation(
301
+ entity,
302
+ pascalName,
303
+ ids
304
+ );
305
+ const data = await transport(query, variables, merged);
306
+ const mutationKey = `delete${pascalName}`;
307
+ return data[mutationKey].data;
308
+ },
309
+ onSuccess: (data, variables, onMutateResult, context) => {
310
+ var _a2;
311
+ if (!isDryRun) {
312
+ void queryClient.invalidateQueries({
313
+ queryKey: ["pylo", entity]
314
+ });
315
+ }
316
+ (_a2 = mutationOptions == null ? void 0 : mutationOptions.onSuccess) == null ? void 0 : _a2.call(mutationOptions, data, variables, onMutateResult, context);
317
+ }
318
+ });
319
+ }
320
+ function usePyloIngestEvents(mutationOptions) {
321
+ const transport = useTransport();
322
+ const merged = mergeHeaders(
323
+ mergeHeaders(globalHeaders, mutationOptions == null ? void 0 : mutationOptions.headers),
324
+ flagsToHeaders(mutationOptions != null ? mutationOptions : {})
325
+ );
326
+ return useMutation({
327
+ ...mutationOptions,
328
+ mutationFn: async (events) => {
329
+ const { query, variables } = buildIngestEventsMutation(events);
330
+ const data = await transport(query, variables, merged);
331
+ return data["ingestPyloEventData"].data;
332
+ }
333
+ });
334
+ }
335
+ function usePyloEventList(queryOptions) {
336
+ const transport = useTransport();
337
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
338
+ return useQuery({
339
+ queryKey: ["pylo", "events", "list", { ...queryOptions, headers: merged }],
340
+ queryFn: async () => {
341
+ const { query, variables } = buildEventListQuery(queryOptions);
342
+ const data = await transport(query, variables, merged);
343
+ return data["pyloEventList"];
344
+ }
345
+ });
346
+ }
347
+ function usePyloEventPropertyKeys(queryOptions) {
348
+ const transport = useTransport();
349
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
350
+ return useQuery({
351
+ queryKey: [
352
+ "pylo",
353
+ "events",
354
+ "propertyKeys",
355
+ { filter: queryOptions == null ? void 0 : queryOptions.filter, headers: merged }
356
+ ],
357
+ queryFn: async () => {
358
+ var _a2;
359
+ const { query, variables } = buildEventPropertyKeysQuery(queryOptions);
360
+ const data = await transport(query, variables, merged);
361
+ return (_a2 = data["pyloEventPropertyKeys"]) != null ? _a2 : [];
362
+ }
363
+ });
364
+ }
365
+ function usePyloEventFieldValues(field, queryOptions) {
366
+ const transport = useTransport();
367
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
368
+ return useQuery({
369
+ queryKey: [
370
+ "pylo",
371
+ "events",
372
+ "fieldValues",
373
+ field,
374
+ {
375
+ startTime: queryOptions == null ? void 0 : queryOptions.startTime,
376
+ limit: queryOptions == null ? void 0 : queryOptions.limit,
377
+ headers: merged
378
+ }
379
+ ],
380
+ queryFn: async () => {
381
+ var _a2;
382
+ const { query, variables } = buildEventFieldValuesQuery(field, queryOptions);
383
+ const data = await transport(query, variables, merged);
384
+ return (_a2 = data["pyloEventFieldValues"]) != null ? _a2 : [];
385
+ },
386
+ enabled: !!field
387
+ });
388
+ }
389
+ function usePyloUpload(hookOptions) {
390
+ const transport = useTransport();
391
+ const queryClient = useQueryClient();
392
+ const [isUploading, setIsUploading] = useState(false);
393
+ const [progress, setProgress] = useState(0);
394
+ const [error, setError] = useState(null);
395
+ const [uploadedFiles, setUploadedFiles] = useState([]);
396
+ const abortRef = useRef(null);
397
+ const optionsRef = useRef(hookOptions);
398
+ optionsRef.current = hookOptions;
399
+ const startUpload = useCallback(
400
+ async (files, overrides) => {
401
+ var _a2, _b, _c, _d;
402
+ const opts = { ...optionsRef.current, ...overrides };
403
+ const merged = mergeHeaders(globalHeaders, opts.headers);
404
+ const list = Array.isArray(files) ? files : [files];
405
+ if (list.length === 0) return [];
406
+ const controller = new AbortController();
407
+ abortRef.current = controller;
408
+ setIsUploading(true);
409
+ setProgress(0);
410
+ setError(null);
411
+ setUploadedFiles([]);
412
+ let parts = [];
413
+ let grandTotal;
414
+ const loadedPerFile = new Array(list.length).fill(0);
415
+ const doneFlags = new Array(list.length).fill(false);
416
+ const reportProgress = () => {
417
+ var _a3, _b2;
418
+ const loaded = loadedPerFile.reduce((sum, bytes) => sum + bytes, 0);
419
+ const percent = grandTotal !== void 0 ? grandTotal > 0 ? Math.round(loaded / grandTotal * 100) : 0 : Math.round(
420
+ doneFlags.filter(Boolean).length / doneFlags.length * 100
421
+ );
422
+ setProgress(percent);
423
+ (_b2 = (_a3 = optionsRef.current) == null ? void 0 : _a3.onProgress) == null ? void 0 : _b2.call(_a3, {
424
+ loaded,
425
+ total: grandTotal != null ? grandTotal : loaded,
426
+ percent
427
+ });
428
+ };
429
+ try {
430
+ parts = list.map((source) => toUploadPart(source));
431
+ const sizes = parts.map((part) => part.size);
432
+ grandTotal = sizes.every((size) => size !== void 0) ? sizes.reduce((sum, size) => sum + (size != null ? size : 0), 0) : void 0;
433
+ const input = buildCreateUploadInput(opts, list.length);
434
+ const results = await Promise.all(
435
+ list.map(async (_source, index) => {
436
+ var _a3, _b2;
437
+ const part = parts[index];
438
+ const data = await transport(
439
+ CREATE_UPLOAD_MUTATION,
440
+ { input },
441
+ merged
442
+ );
443
+ const uploadUrl = data.createUpload;
444
+ await uploadToUrl(uploadUrl.url, part.part, part.fileName, {
445
+ signal: controller.signal,
446
+ onProgress: (fileProgress) => {
447
+ loadedPerFile[index] = fileProgress.loaded;
448
+ reportProgress();
449
+ }
450
+ });
451
+ loadedPerFile[index] = (_a3 = part.size) != null ? _a3 : loadedPerFile[index];
452
+ doneFlags[index] = true;
453
+ reportProgress();
454
+ return {
455
+ id: uploadUrl.id,
456
+ fileName: part.fileName,
457
+ mimeType: part.mimeType,
458
+ size: (_b2 = part.size) != null ? _b2 : 0
459
+ };
460
+ })
461
+ );
462
+ if (opts.attachTo) {
463
+ const { query, variables, entityKey } = buildAttachMutation(
464
+ opts.entityRelationPath,
465
+ results.map((result) => result.id),
466
+ opts.attachTo
467
+ );
468
+ await transport(query, variables, merged);
469
+ void queryClient.invalidateQueries({ queryKey: ["pylo", entityKey] });
470
+ }
471
+ void queryClient.invalidateQueries({ queryKey: ["pylo", "pyloMedia"] });
472
+ setUploadedFiles(results);
473
+ setProgress(100);
474
+ (_b = (_a2 = optionsRef.current) == null ? void 0 : _a2.onSuccess) == null ? void 0 : _b.call(_a2, results);
475
+ return results;
476
+ } catch (thrown) {
477
+ controller.abort();
478
+ const uploadError = thrown instanceof Error ? thrown : new Error(String(thrown));
479
+ setError(uploadError);
480
+ (_d = (_c = optionsRef.current) == null ? void 0 : _c.onError) == null ? void 0 : _d.call(_c, uploadError);
481
+ throw uploadError;
482
+ } finally {
483
+ setIsUploading(false);
484
+ if (abortRef.current === controller) abortRef.current = null;
485
+ }
486
+ },
487
+ [queryClient]
488
+ );
489
+ const abort = useCallback(() => {
490
+ var _a2;
491
+ (_a2 = abortRef.current) == null ? void 0 : _a2.abort();
492
+ }, []);
493
+ const reset = useCallback(() => {
494
+ setIsUploading(false);
495
+ setProgress(0);
496
+ setError(null);
497
+ setUploadedFiles([]);
498
+ }, []);
499
+ return { startUpload, isUploading, progress, error, uploadedFiles, abort, reset };
500
+ }
501
+ function usePyloFileUrl(id, queryOptions) {
502
+ var _a2;
503
+ const transport = useTransport();
504
+ const merged = mergeHeaders(globalHeaders, queryOptions == null ? void 0 : queryOptions.headers);
505
+ return useQuery({
506
+ queryKey: ["pylo", "files", "downloadUrl", id, { headers: merged }],
507
+ queryFn: async () => {
508
+ const data = await transport(
509
+ CREATE_DOWNLOAD_MUTATION,
510
+ { id },
511
+ merged
512
+ );
513
+ return data.createDownload.url;
514
+ },
515
+ enabled: !!id,
516
+ staleTime: (_a2 = queryOptions == null ? void 0 : queryOptions.staleTimeMs) != null ? _a2 : 4 * 60 * 1e3
517
+ });
518
+ }
519
+ return {
520
+ usePyloList,
521
+ usePyloInfiniteList,
522
+ usePyloById,
523
+ usePyloMe,
524
+ usePyloAggregate,
525
+ usePyloEventAggregate,
526
+ usePyloUpsert,
527
+ usePyloBulkUpsert,
528
+ usePyloDelete,
529
+ usePyloIngestEvents,
530
+ usePyloEventList,
531
+ usePyloEventPropertyKeys,
532
+ usePyloEventFieldValues,
533
+ usePyloUpload,
534
+ usePyloFileUrl
535
+ };
536
+ }
537
+
538
+ export {
539
+ createPyloHooks
540
+ };