@safercity/sdk-react 0.0.1
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/README.md +196 -0
- package/dist/index.cjs +505 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +571 -0
- package/dist/index.d.ts +571 -0
- package/dist/index.js +473 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { createSaferCityClient } from '@safercity/sdk';
|
|
2
|
+
export * from '@safercity/sdk';
|
|
3
|
+
import { createContext, useMemo, useContext, useState, useRef, useCallback, useEffect } from 'react';
|
|
4
|
+
import { QueryClient, QueryClientProvider, useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var SaferCityContext = createContext(null);
|
|
8
|
+
function SaferCityProvider({
|
|
9
|
+
children,
|
|
10
|
+
queryClient: externalQueryClient,
|
|
11
|
+
...clientOptions
|
|
12
|
+
}) {
|
|
13
|
+
const client = useMemo(
|
|
14
|
+
() => createSaferCityClient(clientOptions),
|
|
15
|
+
// Only recreate if baseUrl or tenantId changes
|
|
16
|
+
// Token updates should use client.setToken()
|
|
17
|
+
[clientOptions.baseUrl, clientOptions.tenantId]
|
|
18
|
+
);
|
|
19
|
+
useMemo(() => {
|
|
20
|
+
client.setToken(clientOptions.token);
|
|
21
|
+
}, [client, clientOptions.token]);
|
|
22
|
+
const queryClient = useMemo(
|
|
23
|
+
() => externalQueryClient ?? new QueryClient({
|
|
24
|
+
defaultOptions: {
|
|
25
|
+
queries: {
|
|
26
|
+
staleTime: 1e3 * 60,
|
|
27
|
+
// 1 minute
|
|
28
|
+
gcTime: 1e3 * 60 * 5,
|
|
29
|
+
// 5 minutes
|
|
30
|
+
retry: 1,
|
|
31
|
+
refetchOnWindowFocus: false
|
|
32
|
+
},
|
|
33
|
+
mutations: {
|
|
34
|
+
retry: 0
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}),
|
|
38
|
+
[externalQueryClient]
|
|
39
|
+
);
|
|
40
|
+
const contextValue = useMemo(() => ({ client }), [client]);
|
|
41
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(SaferCityContext.Provider, { value: contextValue, children }) });
|
|
42
|
+
}
|
|
43
|
+
function useSaferCity() {
|
|
44
|
+
const context = useContext(SaferCityContext);
|
|
45
|
+
if (!context) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
"useSaferCity must be used within a SaferCityProvider. Make sure your component is wrapped with <SaferCityProvider>."
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return context;
|
|
51
|
+
}
|
|
52
|
+
function useSaferCityClient() {
|
|
53
|
+
return useSaferCity().client;
|
|
54
|
+
}
|
|
55
|
+
var saferCityKeys = {
|
|
56
|
+
all: ["safercity"],
|
|
57
|
+
// Health
|
|
58
|
+
health: () => [...saferCityKeys.all, "health"],
|
|
59
|
+
// Auth
|
|
60
|
+
auth: () => [...saferCityKeys.all, "auth"],
|
|
61
|
+
authWhoami: () => [...saferCityKeys.auth(), "whoami"],
|
|
62
|
+
// Users
|
|
63
|
+
users: () => [...saferCityKeys.all, "users"],
|
|
64
|
+
usersList: (filters) => [...saferCityKeys.users(), "list", filters],
|
|
65
|
+
usersDetail: (userId) => [...saferCityKeys.users(), "detail", userId],
|
|
66
|
+
// Panics
|
|
67
|
+
panics: () => [...saferCityKeys.all, "panics"],
|
|
68
|
+
panicsList: (filters) => [...saferCityKeys.panics(), "list", filters],
|
|
69
|
+
panicsDetail: (panicId) => [...saferCityKeys.panics(), "detail", panicId],
|
|
70
|
+
// Subscriptions
|
|
71
|
+
subscriptions: () => [...saferCityKeys.all, "subscriptions"],
|
|
72
|
+
subscriptionsList: (filters) => [...saferCityKeys.subscriptions(), "list", filters],
|
|
73
|
+
subscriptionsTypes: () => [...saferCityKeys.subscriptions(), "types"],
|
|
74
|
+
subscriptionsStats: () => [...saferCityKeys.subscriptions(), "stats"],
|
|
75
|
+
// Location Safety
|
|
76
|
+
locationSafety: (lat, lng) => [...saferCityKeys.all, "location-safety", lat, lng],
|
|
77
|
+
// Crimes
|
|
78
|
+
crimes: () => [...saferCityKeys.all, "crimes"],
|
|
79
|
+
crimesList: (filters) => [...saferCityKeys.crimes(), "list", filters],
|
|
80
|
+
crimesCategories: () => [...saferCityKeys.crimes(), "categories"],
|
|
81
|
+
crimesTypes: () => [...saferCityKeys.crimes(), "types"]
|
|
82
|
+
};
|
|
83
|
+
function useHealthCheck(options) {
|
|
84
|
+
const client = useSaferCityClient();
|
|
85
|
+
return useQuery({
|
|
86
|
+
queryKey: saferCityKeys.health(),
|
|
87
|
+
queryFn: () => client.health.check(),
|
|
88
|
+
...options
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function useWhoAmI(options) {
|
|
92
|
+
const client = useSaferCityClient();
|
|
93
|
+
return useQuery({
|
|
94
|
+
queryKey: saferCityKeys.authWhoami(),
|
|
95
|
+
queryFn: () => client.auth.whoami(),
|
|
96
|
+
...options
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function useUsers(filters, options) {
|
|
100
|
+
const client = useSaferCityClient();
|
|
101
|
+
return useQuery({
|
|
102
|
+
queryKey: saferCityKeys.usersList(filters),
|
|
103
|
+
queryFn: () => client.users.list(filters),
|
|
104
|
+
...options
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function useUser(userId, options) {
|
|
108
|
+
const client = useSaferCityClient();
|
|
109
|
+
return useQuery({
|
|
110
|
+
queryKey: saferCityKeys.usersDetail(userId),
|
|
111
|
+
queryFn: () => client.users.get(userId),
|
|
112
|
+
enabled: !!userId,
|
|
113
|
+
...options
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function useCreateUser(options) {
|
|
117
|
+
const client = useSaferCityClient();
|
|
118
|
+
const queryClient = useQueryClient();
|
|
119
|
+
return useMutation({
|
|
120
|
+
mutationFn: (data) => client.users.create(data),
|
|
121
|
+
onSuccess: () => {
|
|
122
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.users() });
|
|
123
|
+
},
|
|
124
|
+
...options
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function useUpdateUser(options) {
|
|
128
|
+
const client = useSaferCityClient();
|
|
129
|
+
const queryClient = useQueryClient();
|
|
130
|
+
return useMutation({
|
|
131
|
+
mutationFn: ({ userId, data }) => client.users.update(userId, data),
|
|
132
|
+
onSuccess: (_, { userId }) => {
|
|
133
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.usersDetail(userId) });
|
|
134
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.usersList() });
|
|
135
|
+
},
|
|
136
|
+
...options
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function useDeleteUser(options) {
|
|
140
|
+
const client = useSaferCityClient();
|
|
141
|
+
const queryClient = useQueryClient();
|
|
142
|
+
return useMutation({
|
|
143
|
+
mutationFn: (userId) => client.users.delete(userId),
|
|
144
|
+
onSuccess: () => {
|
|
145
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.users() });
|
|
146
|
+
},
|
|
147
|
+
...options
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function usePanics(filters, options) {
|
|
151
|
+
const client = useSaferCityClient();
|
|
152
|
+
return useQuery({
|
|
153
|
+
queryKey: saferCityKeys.panicsList(filters),
|
|
154
|
+
queryFn: () => client.panics.list(filters),
|
|
155
|
+
...options
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function usePanic(panicId, query, options) {
|
|
159
|
+
const client = useSaferCityClient();
|
|
160
|
+
return useQuery({
|
|
161
|
+
queryKey: saferCityKeys.panicsDetail(panicId),
|
|
162
|
+
queryFn: () => client.panics.get(panicId, query),
|
|
163
|
+
enabled: !!panicId,
|
|
164
|
+
...options
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function useCreatePanic(options) {
|
|
168
|
+
const client = useSaferCityClient();
|
|
169
|
+
const queryClient = useQueryClient();
|
|
170
|
+
return useMutation({
|
|
171
|
+
mutationFn: (data) => client.panics.create(data),
|
|
172
|
+
onSuccess: () => {
|
|
173
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.panics() });
|
|
174
|
+
},
|
|
175
|
+
...options
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function useUpdatePanicLocation(options) {
|
|
179
|
+
const client = useSaferCityClient();
|
|
180
|
+
const queryClient = useQueryClient();
|
|
181
|
+
return useMutation({
|
|
182
|
+
mutationFn: ({ panicId, data }) => client.panics.updateLocation(panicId, data),
|
|
183
|
+
onSuccess: (_, { panicId }) => {
|
|
184
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.panicsDetail(panicId) });
|
|
185
|
+
},
|
|
186
|
+
...options
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function useCancelPanic(options) {
|
|
190
|
+
const client = useSaferCityClient();
|
|
191
|
+
const queryClient = useQueryClient();
|
|
192
|
+
return useMutation({
|
|
193
|
+
mutationFn: ({ panicId, data }) => client.panics.cancel(panicId, data),
|
|
194
|
+
onSuccess: (_, { panicId }) => {
|
|
195
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.panicsDetail(panicId) });
|
|
196
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.panicsList() });
|
|
197
|
+
},
|
|
198
|
+
...options
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
function useSubscriptionTypes(options) {
|
|
202
|
+
const client = useSaferCityClient();
|
|
203
|
+
return useQuery({
|
|
204
|
+
queryKey: saferCityKeys.subscriptionsTypes(),
|
|
205
|
+
queryFn: () => client.subscriptions.listTypes(),
|
|
206
|
+
staleTime: 1e3 * 60 * 10,
|
|
207
|
+
// 10 minutes - types don't change often
|
|
208
|
+
...options
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function useSubscriptions(filters, options) {
|
|
212
|
+
const client = useSaferCityClient();
|
|
213
|
+
return useQuery({
|
|
214
|
+
queryKey: saferCityKeys.subscriptionsList(filters),
|
|
215
|
+
queryFn: () => client.subscriptions.list(filters),
|
|
216
|
+
...options
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
function useSubscriptionStats(options) {
|
|
220
|
+
const client = useSaferCityClient();
|
|
221
|
+
return useQuery({
|
|
222
|
+
queryKey: saferCityKeys.subscriptionsStats(),
|
|
223
|
+
queryFn: () => client.subscriptions.stats(),
|
|
224
|
+
...options
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function useCreateSubscription(options) {
|
|
228
|
+
const client = useSaferCityClient();
|
|
229
|
+
const queryClient = useQueryClient();
|
|
230
|
+
return useMutation({
|
|
231
|
+
mutationFn: (data) => client.subscriptions.create(data),
|
|
232
|
+
onSuccess: () => {
|
|
233
|
+
queryClient.invalidateQueries({ queryKey: saferCityKeys.subscriptions() });
|
|
234
|
+
},
|
|
235
|
+
...options
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function useLocationSafety(latitude, longitude, radius, options) {
|
|
239
|
+
const client = useSaferCityClient();
|
|
240
|
+
return useQuery({
|
|
241
|
+
queryKey: saferCityKeys.locationSafety(latitude, longitude),
|
|
242
|
+
queryFn: () => client.locationSafety.check({ latitude, longitude, radius }),
|
|
243
|
+
enabled: latitude !== void 0 && longitude !== void 0,
|
|
244
|
+
staleTime: 1e3 * 60 * 5,
|
|
245
|
+
// 5 minutes
|
|
246
|
+
...options
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
function useCrimes(filters, options) {
|
|
250
|
+
const client = useSaferCityClient();
|
|
251
|
+
return useQuery({
|
|
252
|
+
queryKey: saferCityKeys.crimesList(filters),
|
|
253
|
+
queryFn: () => client.crimes.list(filters),
|
|
254
|
+
...options
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function useCrimeCategories(options) {
|
|
258
|
+
const client = useSaferCityClient();
|
|
259
|
+
return useQuery({
|
|
260
|
+
queryKey: saferCityKeys.crimesCategories(),
|
|
261
|
+
queryFn: () => client.crimes.categories(),
|
|
262
|
+
staleTime: 1e3 * 60 * 30,
|
|
263
|
+
// 30 minutes - categories rarely change
|
|
264
|
+
...options
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
function useCrimeTypes(options) {
|
|
268
|
+
const client = useSaferCityClient();
|
|
269
|
+
return useQuery({
|
|
270
|
+
queryKey: saferCityKeys.crimesTypes(),
|
|
271
|
+
queryFn: () => client.crimes.types(),
|
|
272
|
+
staleTime: 1e3 * 60 * 30,
|
|
273
|
+
// 30 minutes
|
|
274
|
+
...options
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
function usePanicStream(panicId, options = {}) {
|
|
278
|
+
const client = useSaferCityClient();
|
|
279
|
+
const {
|
|
280
|
+
autoConnect = true,
|
|
281
|
+
keepHistory = false,
|
|
282
|
+
maxHistory = 100,
|
|
283
|
+
transform,
|
|
284
|
+
onOpen,
|
|
285
|
+
onEvent,
|
|
286
|
+
onError,
|
|
287
|
+
onClose
|
|
288
|
+
} = options;
|
|
289
|
+
const [state, setState] = useState({
|
|
290
|
+
data: null,
|
|
291
|
+
events: [],
|
|
292
|
+
isConnected: false,
|
|
293
|
+
isConnecting: false,
|
|
294
|
+
error: null
|
|
295
|
+
});
|
|
296
|
+
const abortControllerRef = useRef(null);
|
|
297
|
+
const isActiveRef = useRef(false);
|
|
298
|
+
const connect = useCallback(async () => {
|
|
299
|
+
if (!panicId || isActiveRef.current) return;
|
|
300
|
+
isActiveRef.current = true;
|
|
301
|
+
abortControllerRef.current = new AbortController();
|
|
302
|
+
setState((prev) => ({
|
|
303
|
+
...prev,
|
|
304
|
+
isConnecting: true,
|
|
305
|
+
error: null
|
|
306
|
+
}));
|
|
307
|
+
try {
|
|
308
|
+
const eventSourceOptions = {
|
|
309
|
+
signal: abortControllerRef.current.signal,
|
|
310
|
+
onOpen: () => {
|
|
311
|
+
setState((prev) => ({
|
|
312
|
+
...prev,
|
|
313
|
+
isConnected: true,
|
|
314
|
+
isConnecting: false
|
|
315
|
+
}));
|
|
316
|
+
onOpen?.();
|
|
317
|
+
},
|
|
318
|
+
onError: (err) => {
|
|
319
|
+
setState((prev) => ({
|
|
320
|
+
...prev,
|
|
321
|
+
isConnected: false,
|
|
322
|
+
isConnecting: false,
|
|
323
|
+
error: err
|
|
324
|
+
}));
|
|
325
|
+
onError?.(err);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
const stream = client.panics.streamUpdates(panicId, eventSourceOptions);
|
|
329
|
+
for await (const event of stream) {
|
|
330
|
+
if (!isActiveRef.current) break;
|
|
331
|
+
const transformedEvent = transform ? transform(event) : event;
|
|
332
|
+
setState((prev) => {
|
|
333
|
+
const newEvents = keepHistory ? [...prev.events, transformedEvent].slice(-maxHistory) : [];
|
|
334
|
+
return {
|
|
335
|
+
...prev,
|
|
336
|
+
data: transformedEvent,
|
|
337
|
+
events: newEvents
|
|
338
|
+
};
|
|
339
|
+
});
|
|
340
|
+
onEvent?.(transformedEvent);
|
|
341
|
+
}
|
|
342
|
+
} catch (err) {
|
|
343
|
+
if (isActiveRef.current) {
|
|
344
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
345
|
+
setState((prev) => ({
|
|
346
|
+
...prev,
|
|
347
|
+
isConnected: false,
|
|
348
|
+
isConnecting: false,
|
|
349
|
+
error
|
|
350
|
+
}));
|
|
351
|
+
onError?.(error);
|
|
352
|
+
}
|
|
353
|
+
} finally {
|
|
354
|
+
isActiveRef.current = false;
|
|
355
|
+
setState((prev) => ({
|
|
356
|
+
...prev,
|
|
357
|
+
isConnected: false,
|
|
358
|
+
isConnecting: false
|
|
359
|
+
}));
|
|
360
|
+
onClose?.();
|
|
361
|
+
}
|
|
362
|
+
}, [panicId, client, transform, keepHistory, maxHistory, onOpen, onEvent, onError, onClose]);
|
|
363
|
+
const disconnect = useCallback(() => {
|
|
364
|
+
isActiveRef.current = false;
|
|
365
|
+
abortControllerRef.current?.abort();
|
|
366
|
+
abortControllerRef.current = null;
|
|
367
|
+
}, []);
|
|
368
|
+
useEffect(() => {
|
|
369
|
+
if (autoConnect && panicId) {
|
|
370
|
+
connect();
|
|
371
|
+
}
|
|
372
|
+
return () => {
|
|
373
|
+
disconnect();
|
|
374
|
+
};
|
|
375
|
+
}, [autoConnect, panicId, connect, disconnect]);
|
|
376
|
+
return {
|
|
377
|
+
...state,
|
|
378
|
+
connect,
|
|
379
|
+
disconnect
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
function useStream(createStream, options = {}) {
|
|
383
|
+
const {
|
|
384
|
+
autoConnect = true,
|
|
385
|
+
keepHistory = false,
|
|
386
|
+
maxHistory = 100,
|
|
387
|
+
transform,
|
|
388
|
+
onOpen,
|
|
389
|
+
onEvent,
|
|
390
|
+
onError,
|
|
391
|
+
onClose
|
|
392
|
+
} = options;
|
|
393
|
+
const [state, setState] = useState({
|
|
394
|
+
data: null,
|
|
395
|
+
events: [],
|
|
396
|
+
isConnected: false,
|
|
397
|
+
isConnecting: false,
|
|
398
|
+
error: null
|
|
399
|
+
});
|
|
400
|
+
const isActiveRef = useRef(false);
|
|
401
|
+
const createStreamRef = useRef(createStream);
|
|
402
|
+
createStreamRef.current = createStream;
|
|
403
|
+
const connect = useCallback(async () => {
|
|
404
|
+
if (isActiveRef.current) return;
|
|
405
|
+
isActiveRef.current = true;
|
|
406
|
+
setState((prev) => ({
|
|
407
|
+
...prev,
|
|
408
|
+
isConnecting: true,
|
|
409
|
+
error: null
|
|
410
|
+
}));
|
|
411
|
+
try {
|
|
412
|
+
const stream = createStreamRef.current();
|
|
413
|
+
setState((prev) => ({
|
|
414
|
+
...prev,
|
|
415
|
+
isConnected: true,
|
|
416
|
+
isConnecting: false
|
|
417
|
+
}));
|
|
418
|
+
onOpen?.();
|
|
419
|
+
for await (const event of stream) {
|
|
420
|
+
if (!isActiveRef.current) break;
|
|
421
|
+
const transformedEvent = transform ? transform(event) : event;
|
|
422
|
+
setState((prev) => {
|
|
423
|
+
const newEvents = keepHistory ? [...prev.events, transformedEvent].slice(-maxHistory) : [];
|
|
424
|
+
return {
|
|
425
|
+
...prev,
|
|
426
|
+
data: transformedEvent,
|
|
427
|
+
events: newEvents
|
|
428
|
+
};
|
|
429
|
+
});
|
|
430
|
+
onEvent?.(transformedEvent);
|
|
431
|
+
}
|
|
432
|
+
} catch (err) {
|
|
433
|
+
if (isActiveRef.current) {
|
|
434
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
435
|
+
setState((prev) => ({
|
|
436
|
+
...prev,
|
|
437
|
+
isConnected: false,
|
|
438
|
+
isConnecting: false,
|
|
439
|
+
error
|
|
440
|
+
}));
|
|
441
|
+
onError?.(error);
|
|
442
|
+
}
|
|
443
|
+
} finally {
|
|
444
|
+
isActiveRef.current = false;
|
|
445
|
+
setState((prev) => ({
|
|
446
|
+
...prev,
|
|
447
|
+
isConnected: false,
|
|
448
|
+
isConnecting: false
|
|
449
|
+
}));
|
|
450
|
+
onClose?.();
|
|
451
|
+
}
|
|
452
|
+
}, [transform, keepHistory, maxHistory, onOpen, onEvent, onError, onClose]);
|
|
453
|
+
const disconnect = useCallback(() => {
|
|
454
|
+
isActiveRef.current = false;
|
|
455
|
+
}, []);
|
|
456
|
+
useEffect(() => {
|
|
457
|
+
if (autoConnect) {
|
|
458
|
+
connect();
|
|
459
|
+
}
|
|
460
|
+
return () => {
|
|
461
|
+
disconnect();
|
|
462
|
+
};
|
|
463
|
+
}, [autoConnect, connect, disconnect]);
|
|
464
|
+
return {
|
|
465
|
+
...state,
|
|
466
|
+
connect,
|
|
467
|
+
disconnect
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export { SaferCityProvider, saferCityKeys, useCancelPanic, useCreatePanic, useCreateSubscription, useCreateUser, useCrimeCategories, useCrimeTypes, useCrimes, useDeleteUser, useHealthCheck, useLocationSafety, usePanic, usePanicStream, usePanics, useSaferCity, useSaferCityClient, useStream, useSubscriptionStats, useSubscriptionTypes, useSubscriptions, useUpdatePanicLocation, useUpdateUser, useUser, useUsers, useWhoAmI };
|
|
472
|
+
//# sourceMappingURL=index.js.map
|
|
473
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/hooks.ts","../src/use-stream.ts"],"names":[],"mappings":";;;;;;AAaA,IAAM,gBAAA,GAAmB,cAA4C,IAAI,CAAA;AAqClE,SAAS,iBAAA,CAAkB;AAAA,EAChC,QAAA;AAAA,EACA,WAAA,EAAa,mBAAA;AAAA,EACb,GAAG;AACL,CAAA,EAA2B;AAEzB,EAAA,MAAM,MAAA,GAAS,OAAA;AAAA,IACb,MAAM,sBAAsB,aAAa,CAAA;AAAA;AAAA;AAAA,IAGzC,CAAC,aAAA,CAAc,OAAA,EAAS,aAAA,CAAc,QAAQ;AAAA,GAChD;AAGA,EAAA,OAAA,CAAQ,MAAM;AACZ,IAAA,MAAA,CAAO,QAAA,CAAS,cAAc,KAAK,CAAA;AAAA,EACrC,CAAA,EAAG,CAAC,MAAA,EAAQ,aAAA,CAAc,KAAK,CAAC,CAAA;AAGhC,EAAA,MAAM,WAAA,GAAc,OAAA;AAAA,IAClB,MAAM,mBAAA,IAAuB,IAAI,WAAA,CAAY;AAAA,MAC3C,cAAA,EAAgB;AAAA,QACd,OAAA,EAAS;AAAA,UACP,WAAW,GAAA,GAAO,EAAA;AAAA;AAAA,UAClB,MAAA,EAAQ,MAAO,EAAA,GAAK,CAAA;AAAA;AAAA,UACpB,KAAA,EAAO,CAAA;AAAA,UACP,oBAAA,EAAsB;AAAA,SACxB;AAAA,QACA,SAAA,EAAW;AAAA,UACT,KAAA,EAAO;AAAA;AACT;AACF,KACD,CAAA;AAAA,IACD,CAAC,mBAAmB;AAAA,GACtB;AAEA,EAAA,MAAM,YAAA,GAAe,QAAQ,OAAO,EAAE,QAAO,CAAA,EAAI,CAAC,MAAM,CAAC,CAAA;AAEzD,EAAA,uBACE,GAAA,CAAC,mBAAA,EAAA,EAAoB,MAAA,EAAQ,WAAA,EAC3B,QAAA,kBAAA,GAAA,CAAC,gBAAA,CAAiB,QAAA,EAAjB,EAA0B,KAAA,EAAO,YAAA,EAC/B,QAAA,EACH,CAAA,EACF,CAAA;AAEJ;AAmBO,SAAS,YAAA,GAAsC;AACpD,EAAA,MAAM,OAAA,GAAU,WAAW,gBAAgB,CAAA;AAE3C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,OAAO,OAAA;AACT;AAOO,SAAS,kBAAA,GAAsC;AACpD,EAAA,OAAO,cAAa,CAAE,MAAA;AACxB;AC5HO,IAAM,aAAA,GAAgB;AAAA,EAC3B,GAAA,EAAK,CAAC,WAAW,CAAA;AAAA;AAAA,EAGjB,QAAQ,MAAM,CAAC,GAAG,aAAA,CAAc,KAAK,QAAQ,CAAA;AAAA;AAAA,EAG7C,MAAM,MAAM,CAAC,GAAG,aAAA,CAAc,KAAK,MAAM,CAAA;AAAA,EACzC,YAAY,MAAM,CAAC,GAAG,aAAA,CAAc,IAAA,IAAQ,QAAQ,CAAA;AAAA;AAAA,EAGpD,OAAO,MAAM,CAAC,GAAG,aAAA,CAAc,KAAK,OAAO,CAAA;AAAA,EAC3C,SAAA,EAAW,CAAC,OAAA,KAAsC,CAAC,GAAG,aAAA,CAAc,KAAA,EAAM,EAAG,MAAA,EAAQ,OAAO,CAAA;AAAA,EAC5F,WAAA,EAAa,CAAC,MAAA,KAAmB,CAAC,GAAG,aAAA,CAAc,KAAA,EAAM,EAAG,QAAA,EAAU,MAAM,CAAA;AAAA;AAAA,EAG5E,QAAQ,MAAM,CAAC,GAAG,aAAA,CAAc,KAAK,QAAQ,CAAA;AAAA,EAC7C,UAAA,EAAY,CAAC,OAAA,KAAsC,CAAC,GAAG,aAAA,CAAc,MAAA,EAAO,EAAG,MAAA,EAAQ,OAAO,CAAA;AAAA,EAC9F,YAAA,EAAc,CAAC,OAAA,KAAoB,CAAC,GAAG,aAAA,CAAc,MAAA,EAAO,EAAG,QAAA,EAAU,OAAO,CAAA;AAAA;AAAA,EAGhF,eAAe,MAAM,CAAC,GAAG,aAAA,CAAc,KAAK,eAAe,CAAA;AAAA,EAC3D,iBAAA,EAAmB,CAAC,OAAA,KAAsC,CAAC,GAAG,aAAA,CAAc,aAAA,EAAc,EAAG,MAAA,EAAQ,OAAO,CAAA;AAAA,EAC5G,oBAAoB,MAAM,CAAC,GAAG,aAAA,CAAc,aAAA,IAAiB,OAAO,CAAA;AAAA,EACpE,oBAAoB,MAAM,CAAC,GAAG,aAAA,CAAc,aAAA,IAAiB,OAAO,CAAA;AAAA;AAAA,EAGpE,cAAA,EAAgB,CAAC,GAAA,EAAa,GAAA,KAAgB,CAAC,GAAG,aAAA,CAAc,GAAA,EAAK,iBAAA,EAAmB,GAAA,EAAK,GAAG,CAAA;AAAA;AAAA,EAGhG,QAAQ,MAAM,CAAC,GAAG,aAAA,CAAc,KAAK,QAAQ,CAAA;AAAA,EAC7C,UAAA,EAAY,CAAC,OAAA,KAAsC,CAAC,GAAG,aAAA,CAAc,MAAA,EAAO,EAAG,MAAA,EAAQ,OAAO,CAAA;AAAA,EAC9F,kBAAkB,MAAM,CAAC,GAAG,aAAA,CAAc,MAAA,IAAU,YAAY,CAAA;AAAA,EAChE,aAAa,MAAM,CAAC,GAAG,aAAA,CAAc,MAAA,IAAU,OAAO;AACxD;AAMO,SAAS,eACd,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,cAAc,MAAA,EAAO;AAAA,IAC/B,OAAA,EAAS,MAAM,MAAA,CAAO,MAAA,CAAO,KAAA,EAAM;AAAA,IACnC,GAAG;AAAA,GACJ,CAAA;AACH;AAMO,SAAS,UACd,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,cAAc,UAAA,EAAW;AAAA,IACnC,OAAA,EAAS,MAAM,MAAA,CAAO,IAAA,CAAK,MAAA,EAAO;AAAA,IAClC,GAAG;AAAA,GACJ,CAAA;AACH;AAMO,SAAS,QAAA,CACd,SACA,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,SAAA,CAAU,OAAO,CAAA;AAAA,IACzC,OAAA,EAAS,MAAM,MAAA,CAAO,KAAA,CAAM,KAAK,OAAO,CAAA;AAAA,IACxC,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,OAAA,CACd,QACA,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,WAAA,CAAY,MAAM,CAAA;AAAA,IAC1C,OAAA,EAAS,MAAM,MAAA,CAAO,KAAA,CAAM,IAAI,MAAM,CAAA;AAAA,IACtC,OAAA,EAAS,CAAC,CAAC,MAAA;AAAA,IACX,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,cACd,OAAA,EAKA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAClC,EAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,YAAY,CAAC,IAAA,KAAS,MAAA,CAAO,KAAA,CAAM,OAAO,IAAI,CAAA;AAAA,IAC9C,WAAW,MAAM;AACf,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,aAAA,CAAc,KAAA,IAAS,CAAA;AAAA,IACnE,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,cACd,OAAA,EAKA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAClC,EAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,UAAA,EAAY,CAAC,EAAE,MAAA,EAAQ,IAAA,OAAW,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,MAAA,EAAQ,IAAI,CAAA;AAAA,IAClE,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,QAAO,KAAM;AAC5B,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,cAAc,WAAA,CAAY,MAAM,GAAG,CAAA;AAC7E,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,aAAA,CAAc,SAAA,IAAa,CAAA;AAAA,IACvE,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,cACd,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAClC,EAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,YAAY,CAAC,MAAA,KAAW,MAAA,CAAO,KAAA,CAAM,OAAO,MAAM,CAAA;AAAA,IAClD,WAAW,MAAM;AACf,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,aAAA,CAAc,KAAA,IAAS,CAAA;AAAA,IACnE,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAMO,SAAS,SAAA,CACd,SACA,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,UAAA,CAAW,OAAO,CAAA;AAAA,IAC1C,OAAA,EAAS,MAAM,MAAA,CAAO,MAAA,CAAO,KAAK,OAAO,CAAA;AAAA,IACzC,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,QAAA,CACd,OAAA,EACA,KAAA,EACA,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,YAAA,CAAa,OAAO,CAAA;AAAA,IAC5C,SAAS,MAAM,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,SAAS,KAAK,CAAA;AAAA,IAC/C,OAAA,EAAS,CAAC,CAAC,OAAA;AAAA,IACX,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,eACd,OAAA,EAKA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAClC,EAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,YAAY,CAAC,IAAA,KAAS,MAAA,CAAO,MAAA,CAAO,OAAO,IAAI,CAAA;AAAA,IAC/C,WAAW,MAAM;AACf,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,aAAA,CAAc,MAAA,IAAU,CAAA;AAAA,IACpE,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,uBACd,OAAA,EAKA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAClC,EAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,UAAA,EAAY,CAAC,EAAE,OAAA,EAAS,IAAA,OAAW,MAAA,CAAO,MAAA,CAAO,cAAA,CAAe,OAAA,EAAS,IAAI,CAAA;AAAA,IAC7E,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,SAAQ,KAAM;AAC7B,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,cAAc,YAAA,CAAa,OAAO,GAAG,CAAA;AAAA,IACjF,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,eACd,OAAA,EAKA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAClC,EAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,UAAA,EAAY,CAAC,EAAE,OAAA,EAAS,IAAA,OAAW,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,IAAI,CAAA;AAAA,IACrE,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,SAAQ,KAAM;AAC7B,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,cAAc,YAAA,CAAa,OAAO,GAAG,CAAA;AAC/E,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,aAAA,CAAc,UAAA,IAAc,CAAA;AAAA,IACxE,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAMO,SAAS,qBACd,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,cAAc,kBAAA,EAAmB;AAAA,IAC3C,OAAA,EAAS,MAAM,MAAA,CAAO,aAAA,CAAc,SAAA,EAAU;AAAA,IAC9C,SAAA,EAAW,MAAO,EAAA,GAAK,EAAA;AAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,gBAAA,CACd,SACA,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,iBAAA,CAAkB,OAAO,CAAA;AAAA,IACjD,OAAA,EAAS,MAAM,MAAA,CAAO,aAAA,CAAc,KAAK,OAAO,CAAA;AAAA,IAChD,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,qBACd,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,cAAc,kBAAA,EAAmB;AAAA,IAC3C,OAAA,EAAS,MAAM,MAAA,CAAO,aAAA,CAAc,KAAA,EAAM;AAAA,IAC1C,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,sBACd,OAAA,EAKA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAClC,EAAA,MAAM,cAAc,cAAA,EAAe;AAEnC,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,YAAY,CAAC,IAAA,KAAS,MAAA,CAAO,aAAA,CAAc,OAAO,IAAI,CAAA;AAAA,IACtD,WAAW,MAAM;AACf,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,aAAA,CAAc,aAAA,IAAiB,CAAA;AAAA,IAC3E,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AAMO,SAAS,iBAAA,CACd,QAAA,EACA,SAAA,EACA,MAAA,EACA,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,cAAA,CAAe,QAAA,EAAU,SAAS,CAAA;AAAA,IAC1D,OAAA,EAAS,MAAM,MAAA,CAAO,cAAA,CAAe,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,MAAA,EAAQ,CAAA;AAAA,IAC1E,OAAA,EAAS,QAAA,KAAa,MAAA,IAAa,SAAA,KAAc,MAAA;AAAA,IACjD,SAAA,EAAW,MAAO,EAAA,GAAK,CAAA;AAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;AAMO,SAAS,SAAA,CACd,SACA,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,UAAA,CAAW,OAAO,CAAA;AAAA,IAC1C,OAAA,EAAS,MAAM,MAAA,CAAO,MAAA,CAAO,KAAK,OAAO,CAAA;AAAA,IACzC,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,mBACd,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,cAAc,gBAAA,EAAiB;AAAA,IACzC,OAAA,EAAS,MAAM,MAAA,CAAO,MAAA,CAAO,UAAA,EAAW;AAAA,IACxC,SAAA,EAAW,MAAO,EAAA,GAAK,EAAA;AAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;AAEO,SAAS,cACd,OAAA,EACA;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAElC,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,cAAc,WAAA,EAAY;AAAA,IACpC,OAAA,EAAS,MAAM,MAAA,CAAO,MAAA,CAAO,KAAA,EAAM;AAAA,IACnC,SAAA,EAAW,MAAO,EAAA,GAAK,EAAA;AAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;ACtRO,SAAS,cAAA,CACd,OAAA,EACA,OAAA,GAA+B,EAAC,EAChC;AACA,EAAA,MAAM,SAAS,kBAAA,EAAmB;AAClC,EAAA,MAAM;AAAA,IACJ,WAAA,GAAc,IAAA;AAAA,IACd,WAAA,GAAc,KAAA;AAAA,IACd,UAAA,GAAa,GAAA;AAAA,IACb,SAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAA,CAAyB;AAAA,IACjD,IAAA,EAAM,IAAA;AAAA,IACN,QAAQ,EAAC;AAAA,IACT,WAAA,EAAa,KAAA;AAAA,IACb,YAAA,EAAc,KAAA;AAAA,IACd,KAAA,EAAO;AAAA,GACR,CAAA;AAED,EAAA,MAAM,kBAAA,GAAqB,OAA+B,IAAI,CAAA;AAC9D,EAAA,MAAM,WAAA,GAAc,OAAO,KAAK,CAAA;AAEhC,EAAA,MAAM,OAAA,GAAU,YAAY,YAAY;AACtC,IAAA,IAAI,CAAC,OAAA,IAAW,WAAA,CAAY,OAAA,EAAS;AAErC,IAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,IAAA,kBAAA,CAAmB,OAAA,GAAU,IAAI,eAAA,EAAgB;AAEjD,IAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,MAClB,GAAG,IAAA;AAAA,MACH,YAAA,EAAc,IAAA;AAAA,MACd,KAAA,EAAO;AAAA,KACT,CAAE,CAAA;AAEF,IAAA,IAAI;AACF,MAAA,MAAM,kBAAA,GAAyC;AAAA,QAC7C,MAAA,EAAQ,mBAAmB,OAAA,CAAQ,MAAA;AAAA,QACnC,QAAQ,MAAM;AACZ,UAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,YAClB,GAAG,IAAA;AAAA,YACH,WAAA,EAAa,IAAA;AAAA,YACb,YAAA,EAAc;AAAA,WAChB,CAAE,CAAA;AACF,UAAA,MAAA,IAAS;AAAA,QACX,CAAA;AAAA,QACA,OAAA,EAAS,CAAC,GAAA,KAAQ;AAChB,UAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,YAClB,GAAG,IAAA;AAAA,YACH,WAAA,EAAa,KAAA;AAAA,YACb,YAAA,EAAc,KAAA;AAAA,YACd,KAAA,EAAO;AAAA,WACT,CAAE,CAAA;AACF,UAAA,OAAA,GAAU,GAAG,CAAA;AAAA,QACf;AAAA,OACF;AAEA,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,SAAS,kBAAkB,CAAA;AAEtE,MAAA,WAAA,MAAiB,SAAS,MAAA,EAAQ;AAChC,QAAA,IAAI,CAAC,YAAY,OAAA,EAAS;AAE1B,QAAA,MAAM,gBAAA,GAAmB,SAAA,GAAY,SAAA,CAAU,KAAK,CAAA,GAAK,KAAA;AAEzD,QAAA,QAAA,CAAS,CAAC,IAAA,KAAS;AACjB,UAAA,MAAM,SAAA,GAAY,WAAA,GACd,CAAC,GAAG,IAAA,CAAK,MAAA,EAAQ,gBAAgB,CAAA,CAAE,KAAA,CAAM,CAAC,UAAU,CAAA,GACpD,EAAC;AAEL,UAAA,OAAO;AAAA,YACL,GAAG,IAAA;AAAA,YACH,IAAA,EAAM,gBAAA;AAAA,YACN,MAAA,EAAQ;AAAA,WACV;AAAA,QACF,CAAC,CAAA;AAED,QAAA,OAAA,GAAU,gBAAgB,CAAA;AAAA,MAC5B;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,YAAY,OAAA,EAAS;AACvB,QAAA,MAAM,KAAA,GAAQ,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAChE,QAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,UAClB,GAAG,IAAA;AAAA,UACH,WAAA,EAAa,KAAA;AAAA,UACb,YAAA,EAAc,KAAA;AAAA,UACd;AAAA,SACF,CAAE,CAAA;AACF,QAAA,OAAA,GAAU,KAAK,CAAA;AAAA,MACjB;AAAA,IACF,CAAA,SAAE;AACA,MAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,MAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,QAClB,GAAG,IAAA;AAAA,QACH,WAAA,EAAa,KAAA;AAAA,QACb,YAAA,EAAc;AAAA,OAChB,CAAE,CAAA;AACF,MAAA,OAAA,IAAU;AAAA,IACZ;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,WAAA,EAAa,UAAA,EAAY,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAS,OAAO,CAAC,CAAA;AAE3F,EAAA,MAAM,UAAA,GAAa,YAAY,MAAM;AACnC,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,IAAA,kBAAA,CAAmB,SAAS,KAAA,EAAM;AAClC,IAAA,kBAAA,CAAmB,OAAA,GAAU,IAAA;AAAA,EAC/B,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,MAAA,OAAA,EAAQ;AAAA,IACV;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,UAAA,EAAW;AAAA,IACb,CAAA;AAAA,EACF,GAAG,CAAC,WAAA,EAAa,OAAA,EAAS,OAAA,EAAS,UAAU,CAAC,CAAA;AAE9C,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,OAAA;AAAA,IACA;AAAA,GACF;AACF;AAKO,SAAS,SAAA,CACd,YAAA,EACA,OAAA,GAA+B,EAAC,EAChC;AACA,EAAA,MAAM;AAAA,IACJ,WAAA,GAAc,IAAA;AAAA,IACd,WAAA,GAAc,KAAA;AAAA,IACd,UAAA,GAAa,GAAA;AAAA,IACb,SAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAA,CAAyB;AAAA,IACjD,IAAA,EAAM,IAAA;AAAA,IACN,QAAQ,EAAC;AAAA,IACT,WAAA,EAAa,KAAA;AAAA,IACb,YAAA,EAAc,KAAA;AAAA,IACd,KAAA,EAAO;AAAA,GACR,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,OAAO,KAAK,CAAA;AAChC,EAAA,MAAM,eAAA,GAAkB,OAAO,YAAY,CAAA;AAC3C,EAAA,eAAA,CAAgB,OAAA,GAAU,YAAA;AAE1B,EAAA,MAAM,OAAA,GAAU,YAAY,YAAY;AACtC,IAAA,IAAI,YAAY,OAAA,EAAS;AAEzB,IAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AAEtB,IAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,MAClB,GAAG,IAAA;AAAA,MACH,YAAA,EAAc,IAAA;AAAA,MACd,KAAA,EAAO;AAAA,KACT,CAAE,CAAA;AAEF,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,gBAAgB,OAAA,EAAQ;AAEvC,MAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,QAClB,GAAG,IAAA;AAAA,QACH,WAAA,EAAa,IAAA;AAAA,QACb,YAAA,EAAc;AAAA,OAChB,CAAE,CAAA;AACF,MAAA,MAAA,IAAS;AAET,MAAA,WAAA,MAAiB,SAAS,MAAA,EAAQ;AAChC,QAAA,IAAI,CAAC,YAAY,OAAA,EAAS;AAE1B,QAAA,MAAM,gBAAA,GAAmB,SAAA,GAAY,SAAA,CAAU,KAAK,CAAA,GAAK,KAAA;AAEzD,QAAA,QAAA,CAAS,CAAC,IAAA,KAAS;AACjB,UAAA,MAAM,SAAA,GAAY,WAAA,GACd,CAAC,GAAG,IAAA,CAAK,MAAA,EAAQ,gBAAgB,CAAA,CAAE,KAAA,CAAM,CAAC,UAAU,CAAA,GACpD,EAAC;AAEL,UAAA,OAAO;AAAA,YACL,GAAG,IAAA;AAAA,YACH,IAAA,EAAM,gBAAA;AAAA,YACN,MAAA,EAAQ;AAAA,WACV;AAAA,QACF,CAAC,CAAA;AAED,QAAA,OAAA,GAAU,gBAAgB,CAAA;AAAA,MAC5B;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,YAAY,OAAA,EAAS;AACvB,QAAA,MAAM,KAAA,GAAQ,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAChE,QAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,UAClB,GAAG,IAAA;AAAA,UACH,WAAA,EAAa,KAAA;AAAA,UACb,YAAA,EAAc,KAAA;AAAA,UACd;AAAA,SACF,CAAE,CAAA;AACF,QAAA,OAAA,GAAU,KAAK,CAAA;AAAA,MACjB;AAAA,IACF,CAAA,SAAE;AACA,MAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,MAAA,QAAA,CAAS,CAAC,IAAA,MAAU;AAAA,QAClB,GAAG,IAAA;AAAA,QACH,WAAA,EAAa,KAAA;AAAA,QACb,YAAA,EAAc;AAAA,OAChB,CAAE,CAAA;AACF,MAAA,OAAA,IAAU;AAAA,IACZ;AAAA,EACF,CAAA,EAAG,CAAC,SAAA,EAAW,WAAA,EAAa,YAAY,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAS,OAAO,CAAC,CAAA;AAE1E,EAAA,MAAM,UAAA,GAAa,YAAY,MAAM;AACnC,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AAAA,EACxB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,OAAA,EAAQ;AAAA,IACV;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,UAAA,EAAW;AAAA,IACb,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,WAAA,EAAa,OAAA,EAAS,UAAU,CAAC,CAAA;AAErC,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,OAAA;AAAA,IACA;AAAA,GACF;AACF","file":"index.js","sourcesContent":["'use client';\n\nimport { createContext, useContext, useMemo, type ReactNode } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { createSaferCityClient, type SaferCityClient, type SaferCityClientOptions } from '@safercity/sdk';\n\n/**\n * Context value for SaferCity provider\n */\ninterface SaferCityContextValue {\n client: SaferCityClient;\n}\n\nconst SaferCityContext = createContext<SaferCityContextValue | null>(null);\n\n/**\n * Props for SaferCityProvider\n */\nexport interface SaferCityProviderProps extends SaferCityClientOptions {\n children: ReactNode;\n \n /**\n * Custom QueryClient instance (optional)\n * If not provided, a new QueryClient will be created\n */\n queryClient?: QueryClient;\n}\n\n/**\n * Provider component for SaferCity SDK\n * \n * Wraps your app with the SaferCity client context and TanStack Query provider.\n * \n * @example\n * ```tsx\n * import { SaferCityProvider } from '@safercity/sdk-react';\n * \n * function App() {\n * return (\n * <SaferCityProvider\n * baseUrl=\"https://api.safercity.com\"\n * token={userToken}\n * tenantId=\"tenant-123\"\n * >\n * <YourApp />\n * </SaferCityProvider>\n * );\n * }\n * ```\n */\nexport function SaferCityProvider({\n children,\n queryClient: externalQueryClient,\n ...clientOptions\n}: SaferCityProviderProps) {\n // Create client instance (memoized)\n const client = useMemo(\n () => createSaferCityClient(clientOptions),\n // Only recreate if baseUrl or tenantId changes\n // Token updates should use client.setToken()\n [clientOptions.baseUrl, clientOptions.tenantId]\n );\n\n // Update token when it changes\n useMemo(() => {\n client.setToken(clientOptions.token);\n }, [client, clientOptions.token]);\n\n // Create or use provided QueryClient\n const queryClient = useMemo(\n () => externalQueryClient ?? new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 1000 * 60, // 1 minute\n gcTime: 1000 * 60 * 5, // 5 minutes\n retry: 1,\n refetchOnWindowFocus: false,\n },\n mutations: {\n retry: 0,\n },\n },\n }),\n [externalQueryClient]\n );\n\n const contextValue = useMemo(() => ({ client }), [client]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <SaferCityContext.Provider value={contextValue}>\n {children}\n </SaferCityContext.Provider>\n </QueryClientProvider>\n );\n}\n\n/**\n * Hook to access the SaferCity client\n * \n * Must be used within a SaferCityProvider.\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const { client } = useSaferCity();\n * \n * const handleClick = async () => {\n * const { data } = await client.health.check();\n * console.log(data);\n * };\n * }\n * ```\n */\nexport function useSaferCity(): SaferCityContextValue {\n const context = useContext(SaferCityContext);\n \n if (!context) {\n throw new Error(\n 'useSaferCity must be used within a SaferCityProvider. ' +\n 'Make sure your component is wrapped with <SaferCityProvider>.'\n );\n }\n \n return context;\n}\n\n/**\n * Hook to access just the SaferCity client\n * \n * Convenience wrapper around useSaferCity().\n */\nexport function useSaferCityClient(): SaferCityClient {\n return useSaferCity().client;\n}\n","'use client';\n\nimport { useQuery, useMutation, useQueryClient, type UseQueryOptions, type UseMutationOptions } from '@tanstack/react-query';\nimport { useSaferCityClient } from './provider';\nimport type { ApiResponse, SaferCityApiError } from '@safercity/sdk';\n\n// ==================\n// Query Keys Factory\n// ==================\n\nexport const saferCityKeys = {\n all: ['safercity'] as const,\n \n // Health\n health: () => [...saferCityKeys.all, 'health'] as const,\n \n // Auth\n auth: () => [...saferCityKeys.all, 'auth'] as const,\n authWhoami: () => [...saferCityKeys.auth(), 'whoami'] as const,\n \n // Users\n users: () => [...saferCityKeys.all, 'users'] as const,\n usersList: (filters?: Record<string, unknown>) => [...saferCityKeys.users(), 'list', filters] as const,\n usersDetail: (userId: string) => [...saferCityKeys.users(), 'detail', userId] as const,\n \n // Panics\n panics: () => [...saferCityKeys.all, 'panics'] as const,\n panicsList: (filters?: Record<string, unknown>) => [...saferCityKeys.panics(), 'list', filters] as const,\n panicsDetail: (panicId: string) => [...saferCityKeys.panics(), 'detail', panicId] as const,\n \n // Subscriptions\n subscriptions: () => [...saferCityKeys.all, 'subscriptions'] as const,\n subscriptionsList: (filters?: Record<string, unknown>) => [...saferCityKeys.subscriptions(), 'list', filters] as const,\n subscriptionsTypes: () => [...saferCityKeys.subscriptions(), 'types'] as const,\n subscriptionsStats: () => [...saferCityKeys.subscriptions(), 'stats'] as const,\n \n // Location Safety\n locationSafety: (lat: number, lng: number) => [...saferCityKeys.all, 'location-safety', lat, lng] as const,\n \n // Crimes\n crimes: () => [...saferCityKeys.all, 'crimes'] as const,\n crimesList: (filters?: Record<string, unknown>) => [...saferCityKeys.crimes(), 'list', filters] as const,\n crimesCategories: () => [...saferCityKeys.crimes(), 'categories'] as const,\n crimesTypes: () => [...saferCityKeys.crimes(), 'types'] as const,\n};\n\n// ==================\n// Health Hooks\n// ==================\n\nexport function useHealthCheck(\n options?: Omit<UseQueryOptions<ApiResponse<{ status: string; timestamp: string }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.health(),\n queryFn: () => client.health.check(),\n ...options,\n });\n}\n\n// ==================\n// Auth Hooks\n// ==================\n\nexport function useWhoAmI(\n options?: Omit<UseQueryOptions<ApiResponse<{ tenantId: string | null; environment: string; scopes: string[]; sessionId: string }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.authWhoami(),\n queryFn: () => client.auth.whoami(),\n ...options,\n });\n}\n\n// ==================\n// User Hooks\n// ==================\n\nexport function useUsers(\n filters?: { limit?: number; cursor?: string; status?: string },\n options?: Omit<UseQueryOptions<ApiResponse<{ users: Array<{ id: string; email?: string; phone?: string; status: string }>; hasNext: boolean; cursor?: string }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.usersList(filters),\n queryFn: () => client.users.list(filters),\n ...options,\n });\n}\n\nexport function useUser(\n userId: string,\n options?: Omit<UseQueryOptions<ApiResponse<{ id: string; email?: string; phone?: string; firstName?: string; lastName?: string; status: string; metadata?: Record<string, unknown> }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.usersDetail(userId),\n queryFn: () => client.users.get(userId),\n enabled: !!userId,\n ...options,\n });\n}\n\nexport function useCreateUser(\n options?: UseMutationOptions<\n ApiResponse<{ id: string; email?: string; phone?: string }>,\n SaferCityApiError,\n { email?: string; phone?: string; firstName?: string; lastName?: string; metadata?: Record<string, unknown> }\n >\n) {\n const client = useSaferCityClient();\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: (data) => client.users.create(data),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: saferCityKeys.users() });\n },\n ...options,\n });\n}\n\nexport function useUpdateUser(\n options?: UseMutationOptions<\n ApiResponse<{ id: string }>,\n SaferCityApiError,\n { userId: string; data: { email?: string; phone?: string; firstName?: string; lastName?: string; metadata?: Record<string, unknown> } }\n >\n) {\n const client = useSaferCityClient();\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: ({ userId, data }) => client.users.update(userId, data),\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({ queryKey: saferCityKeys.usersDetail(userId) });\n queryClient.invalidateQueries({ queryKey: saferCityKeys.usersList() });\n },\n ...options,\n });\n}\n\nexport function useDeleteUser(\n options?: UseMutationOptions<ApiResponse<{ success: boolean }>, SaferCityApiError, string>\n) {\n const client = useSaferCityClient();\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: (userId) => client.users.delete(userId),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: saferCityKeys.users() });\n },\n ...options,\n });\n}\n\n// ==================\n// Panic Hooks\n// ==================\n\nexport function usePanics(\n filters?: { userId?: string; status?: string; limit?: number; cursor?: string },\n options?: Omit<UseQueryOptions<ApiResponse<{ panics: Array<{ id: string; userId: string; status: string; createdAt: string }>; hasNext: boolean; cursor?: string }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.panicsList(filters),\n queryFn: () => client.panics.list(filters),\n ...options,\n });\n}\n\nexport function usePanic(\n panicId: string,\n query?: { userId?: string },\n options?: Omit<UseQueryOptions<ApiResponse<{ id: string; userId: string; status: string; latitude: number; longitude: number; createdAt: string; updatedAt?: string }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.panicsDetail(panicId),\n queryFn: () => client.panics.get(panicId, query),\n enabled: !!panicId,\n ...options,\n });\n}\n\nexport function useCreatePanic(\n options?: UseMutationOptions<\n ApiResponse<{ id: string; status: string; createdAt: string }>,\n SaferCityApiError,\n { userId: string; panicTypeId?: string; latitude: number; longitude: number; accuracy?: number; metadata?: Record<string, unknown> }\n >\n) {\n const client = useSaferCityClient();\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: (data) => client.panics.create(data),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: saferCityKeys.panics() });\n },\n ...options,\n });\n}\n\nexport function useUpdatePanicLocation(\n options?: UseMutationOptions<\n ApiResponse<{ id: string; latitude: number; longitude: number }>,\n SaferCityApiError,\n { panicId: string; data: { userId: string; latitude: number; longitude: number; accuracy?: number } }\n >\n) {\n const client = useSaferCityClient();\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: ({ panicId, data }) => client.panics.updateLocation(panicId, data),\n onSuccess: (_, { panicId }) => {\n queryClient.invalidateQueries({ queryKey: saferCityKeys.panicsDetail(panicId) });\n },\n ...options,\n });\n}\n\nexport function useCancelPanic(\n options?: UseMutationOptions<\n ApiResponse<{ id: string; status: string; cancelledAt: string }>,\n SaferCityApiError,\n { panicId: string; data: { userId: string; reason?: string } }\n >\n) {\n const client = useSaferCityClient();\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: ({ panicId, data }) => client.panics.cancel(panicId, data),\n onSuccess: (_, { panicId }) => {\n queryClient.invalidateQueries({ queryKey: saferCityKeys.panicsDetail(panicId) });\n queryClient.invalidateQueries({ queryKey: saferCityKeys.panicsList() });\n },\n ...options,\n });\n}\n\n// ==================\n// Subscription Hooks\n// ==================\n\nexport function useSubscriptionTypes(\n options?: Omit<UseQueryOptions<ApiResponse<{ types: Array<{ id: string; name: string; description?: string; price?: number }> }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.subscriptionsTypes(),\n queryFn: () => client.subscriptions.listTypes(),\n staleTime: 1000 * 60 * 10, // 10 minutes - types don't change often\n ...options,\n });\n}\n\nexport function useSubscriptions(\n filters?: { userId?: string; status?: string; limit?: number },\n options?: Omit<UseQueryOptions<ApiResponse<{ subscriptions: Array<{ id: string; userId: string; subscriptionTypeId: string; status: string }> }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.subscriptionsList(filters),\n queryFn: () => client.subscriptions.list(filters),\n ...options,\n });\n}\n\nexport function useSubscriptionStats(\n options?: Omit<UseQueryOptions<ApiResponse<{ total: number; active: number; byType: Record<string, number> }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.subscriptionsStats(),\n queryFn: () => client.subscriptions.stats(),\n ...options,\n });\n}\n\nexport function useCreateSubscription(\n options?: UseMutationOptions<\n ApiResponse<{ id: string; userId: string; subscriptionTypeId: string; status: string }>,\n SaferCityApiError,\n { userId: string; subscriptionTypeId: string; status?: string }\n >\n) {\n const client = useSaferCityClient();\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: (data) => client.subscriptions.create(data),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: saferCityKeys.subscriptions() });\n },\n ...options,\n });\n}\n\n// ==================\n// Location Safety Hooks\n// ==================\n\nexport function useLocationSafety(\n latitude: number,\n longitude: number,\n radius?: number,\n options?: Omit<UseQueryOptions<ApiResponse<{ safetyScore: number; riskLevel: string; factors: Array<{ type: string; impact: number }> }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.locationSafety(latitude, longitude),\n queryFn: () => client.locationSafety.check({ latitude, longitude, radius }),\n enabled: latitude !== undefined && longitude !== undefined,\n staleTime: 1000 * 60 * 5, // 5 minutes\n ...options,\n });\n}\n\n// ==================\n// Crime Hooks\n// ==================\n\nexport function useCrimes(\n filters?: { latitude?: number; longitude?: number; radius?: number; type?: string; from?: string; to?: string; limit?: number },\n options?: Omit<UseQueryOptions<ApiResponse<{ crimes: Array<{ id: string; type: string; latitude: number; longitude: number; occurredAt: string }> }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.crimesList(filters),\n queryFn: () => client.crimes.list(filters),\n ...options,\n });\n}\n\nexport function useCrimeCategories(\n options?: Omit<UseQueryOptions<ApiResponse<{ categories: Array<{ id: string; name: string }> }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.crimesCategories(),\n queryFn: () => client.crimes.categories(),\n staleTime: 1000 * 60 * 30, // 30 minutes - categories rarely change\n ...options,\n });\n}\n\nexport function useCrimeTypes(\n options?: Omit<UseQueryOptions<ApiResponse<{ types: Array<{ id: string; name: string; categoryId: string }> }>, SaferCityApiError>, 'queryKey' | 'queryFn'>\n) {\n const client = useSaferCityClient();\n \n return useQuery({\n queryKey: saferCityKeys.crimesTypes(),\n queryFn: () => client.crimes.types(),\n staleTime: 1000 * 60 * 30, // 30 minutes\n ...options,\n });\n}\n","'use client';\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport { useSaferCityClient } from './provider';\nimport type { ServerSentEvent, EventSourceOptions } from '@safercity/sdk';\n\n/**\n * State for streaming hooks\n */\nexport interface StreamState<T = ServerSentEvent> {\n /**\n * Latest event received\n */\n data: T | null;\n \n /**\n * All events received (if keepHistory is true)\n */\n events: T[];\n \n /**\n * Whether the stream is currently connected\n */\n isConnected: boolean;\n \n /**\n * Whether the stream is connecting\n */\n isConnecting: boolean;\n \n /**\n * Error if connection failed\n */\n error: Error | null;\n}\n\nexport interface UseStreamOptions<T = ServerSentEvent> {\n /**\n * Whether to automatically connect on mount\n * @default true\n */\n autoConnect?: boolean;\n \n /**\n * Keep history of all events\n * @default false\n */\n keepHistory?: boolean;\n \n /**\n * Maximum number of events to keep in history\n * @default 100\n */\n maxHistory?: number;\n \n /**\n * Transform raw SSE event to custom type\n */\n transform?: (event: ServerSentEvent) => T;\n \n /**\n * Callback when connected\n */\n onOpen?: () => void;\n \n /**\n * Callback on each event\n */\n onEvent?: (event: T) => void;\n \n /**\n * Callback on error\n */\n onError?: (error: Error) => void;\n \n /**\n * Callback when disconnected\n */\n onClose?: () => void;\n}\n\n/**\n * Hook for streaming panic updates\n * \n * @example\n * ```tsx\n * function PanicTracker({ panicId }: { panicId: string }) {\n * const { data, isConnected, error } = usePanicStream(panicId, {\n * onEvent: (event) => console.log('Update:', event),\n * });\n * \n * if (error) return <div>Error: {error.message}</div>;\n * if (!isConnected) return <div>Connecting...</div>;\n * \n * return <div>Latest: {data?.data}</div>;\n * }\n * ```\n */\nexport function usePanicStream<T = ServerSentEvent>(\n panicId: string | null | undefined,\n options: UseStreamOptions<T> = {}\n) {\n const client = useSaferCityClient();\n const {\n autoConnect = true,\n keepHistory = false,\n maxHistory = 100,\n transform,\n onOpen,\n onEvent,\n onError,\n onClose,\n } = options;\n\n const [state, setState] = useState<StreamState<T>>({\n data: null,\n events: [],\n isConnected: false,\n isConnecting: false,\n error: null,\n });\n\n const abortControllerRef = useRef<AbortController | null>(null);\n const isActiveRef = useRef(false);\n\n const connect = useCallback(async () => {\n if (!panicId || isActiveRef.current) return;\n\n isActiveRef.current = true;\n abortControllerRef.current = new AbortController();\n\n setState((prev) => ({\n ...prev,\n isConnecting: true,\n error: null,\n }));\n\n try {\n const eventSourceOptions: EventSourceOptions = {\n signal: abortControllerRef.current.signal,\n onOpen: () => {\n setState((prev) => ({\n ...prev,\n isConnected: true,\n isConnecting: false,\n }));\n onOpen?.();\n },\n onError: (err) => {\n setState((prev) => ({\n ...prev,\n isConnected: false,\n isConnecting: false,\n error: err,\n }));\n onError?.(err);\n },\n };\n\n const stream = client.panics.streamUpdates(panicId, eventSourceOptions);\n\n for await (const event of stream) {\n if (!isActiveRef.current) break;\n\n const transformedEvent = transform ? transform(event) : (event as unknown as T);\n\n setState((prev) => {\n const newEvents = keepHistory\n ? [...prev.events, transformedEvent].slice(-maxHistory)\n : [];\n\n return {\n ...prev,\n data: transformedEvent,\n events: newEvents,\n };\n });\n\n onEvent?.(transformedEvent);\n }\n } catch (err) {\n if (isActiveRef.current) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState((prev) => ({\n ...prev,\n isConnected: false,\n isConnecting: false,\n error,\n }));\n onError?.(error);\n }\n } finally {\n isActiveRef.current = false;\n setState((prev) => ({\n ...prev,\n isConnected: false,\n isConnecting: false,\n }));\n onClose?.();\n }\n }, [panicId, client, transform, keepHistory, maxHistory, onOpen, onEvent, onError, onClose]);\n\n const disconnect = useCallback(() => {\n isActiveRef.current = false;\n abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n }, []);\n\n // Auto-connect when panicId changes\n useEffect(() => {\n if (autoConnect && panicId) {\n connect();\n }\n\n return () => {\n disconnect();\n };\n }, [autoConnect, panicId, connect, disconnect]);\n\n return {\n ...state,\n connect,\n disconnect,\n };\n}\n\n/**\n * Generic hook for any SSE stream\n */\nexport function useStream<T = ServerSentEvent>(\n createStream: () => AsyncIterable<ServerSentEvent>,\n options: UseStreamOptions<T> = {}\n) {\n const {\n autoConnect = true,\n keepHistory = false,\n maxHistory = 100,\n transform,\n onOpen,\n onEvent,\n onError,\n onClose,\n } = options;\n\n const [state, setState] = useState<StreamState<T>>({\n data: null,\n events: [],\n isConnected: false,\n isConnecting: false,\n error: null,\n });\n\n const isActiveRef = useRef(false);\n const createStreamRef = useRef(createStream);\n createStreamRef.current = createStream;\n\n const connect = useCallback(async () => {\n if (isActiveRef.current) return;\n\n isActiveRef.current = true;\n\n setState((prev) => ({\n ...prev,\n isConnecting: true,\n error: null,\n }));\n\n try {\n const stream = createStreamRef.current();\n\n setState((prev) => ({\n ...prev,\n isConnected: true,\n isConnecting: false,\n }));\n onOpen?.();\n\n for await (const event of stream) {\n if (!isActiveRef.current) break;\n\n const transformedEvent = transform ? transform(event) : (event as unknown as T);\n\n setState((prev) => {\n const newEvents = keepHistory\n ? [...prev.events, transformedEvent].slice(-maxHistory)\n : [];\n\n return {\n ...prev,\n data: transformedEvent,\n events: newEvents,\n };\n });\n\n onEvent?.(transformedEvent);\n }\n } catch (err) {\n if (isActiveRef.current) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState((prev) => ({\n ...prev,\n isConnected: false,\n isConnecting: false,\n error,\n }));\n onError?.(error);\n }\n } finally {\n isActiveRef.current = false;\n setState((prev) => ({\n ...prev,\n isConnected: false,\n isConnecting: false,\n }));\n onClose?.();\n }\n }, [transform, keepHistory, maxHistory, onOpen, onEvent, onError, onClose]);\n\n const disconnect = useCallback(() => {\n isActiveRef.current = false;\n }, []);\n\n useEffect(() => {\n if (autoConnect) {\n connect();\n }\n\n return () => {\n disconnect();\n };\n }, [autoConnect, connect, disconnect]);\n\n return {\n ...state,\n connect,\n disconnect,\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@safercity/sdk-react",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "React hooks and components for SaferCity SDK with TanStack Query integration",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "SaferCity"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/safercity/safercity-v2.git",
|
|
12
|
+
"directory": "packages/sdk/react"
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["safercity", "sdk", "react", "hooks", "tanstack-query"],
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"require": "./dist/index.cjs"
|
|
25
|
+
},
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"CHANGELOG.md"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsup",
|
|
38
|
+
"dev": "tsup --watch",
|
|
39
|
+
"check-types": "tsc --noEmit",
|
|
40
|
+
"clean": "rm -rf dist",
|
|
41
|
+
"prepublishOnly": "bun run build"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@safercity/sdk": "workspace:*",
|
|
45
|
+
"@safercity/sdk-core": "workspace:*"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@tanstack/react-query": ">=5.0.0",
|
|
49
|
+
"react": ">=18.0.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@tanstack/react-query": "^5.0.0",
|
|
53
|
+
"@types/react": "^18.0.0",
|
|
54
|
+
"react": "^18.0.0",
|
|
55
|
+
"tsup": "^8.0.0",
|
|
56
|
+
"typescript": "^5.8.0"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public",
|
|
60
|
+
"registry": "https://registry.npmjs.org/"
|
|
61
|
+
}
|
|
62
|
+
}
|