@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/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":"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","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
+ }