@safercity/sdk-react 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +209 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +91 -40
- package/dist/index.d.ts +91 -40
- package/dist/index.js +208 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6,20 +6,187 @@ var reactQuery = require('@tanstack/react-query');
|
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
|
|
8
8
|
var SaferCityContext = react.createContext(null);
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
function isProxyMode(props) {
|
|
10
|
+
return !("mode" in props) || props.mode === "proxy" || props.mode === void 0;
|
|
11
|
+
}
|
|
12
|
+
function isDirectMode(props) {
|
|
13
|
+
return "mode" in props && props.mode === "direct";
|
|
14
|
+
}
|
|
15
|
+
function isCookieMode(props) {
|
|
16
|
+
return "mode" in props && props.mode === "cookie";
|
|
17
|
+
}
|
|
18
|
+
function isLegacyMode(props) {
|
|
19
|
+
return "baseUrl" in props && "token" in props && !("mode" in props);
|
|
20
|
+
}
|
|
21
|
+
function SaferCityProvider(props) {
|
|
22
|
+
const { children, queryClient: externalQueryClient } = props;
|
|
23
|
+
const mode = react.useMemo(() => {
|
|
24
|
+
if (isDirectMode(props)) return "direct";
|
|
25
|
+
if (isCookieMode(props)) return "cookie";
|
|
26
|
+
return "proxy";
|
|
27
|
+
}, [props]);
|
|
28
|
+
const [session, setSession] = react.useState({
|
|
29
|
+
isAuthenticated: false,
|
|
30
|
+
isLoading: mode === "cookie"
|
|
31
|
+
});
|
|
32
|
+
const client = react.useMemo(() => {
|
|
33
|
+
if (isLegacyMode(props)) {
|
|
34
|
+
return sdk.createSaferCityClient({
|
|
35
|
+
baseUrl: props.baseUrl,
|
|
36
|
+
token: props.token,
|
|
37
|
+
tenantId: props.tenantId,
|
|
38
|
+
fetch: props.fetch,
|
|
39
|
+
timeout: props.timeout,
|
|
40
|
+
headers: props.headers
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (isProxyMode(props)) {
|
|
44
|
+
const proxyBaseUrl = props.proxyBaseUrl ?? "/api/safercity";
|
|
45
|
+
return sdk.createSaferCityClient({
|
|
46
|
+
baseUrl: proxyBaseUrl
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (isDirectMode(props)) {
|
|
50
|
+
return sdk.createSaferCityClient({
|
|
51
|
+
baseUrl: props.baseUrl,
|
|
52
|
+
tenantId: props.tenantId
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (isCookieMode(props)) {
|
|
56
|
+
return sdk.createSaferCityClient({
|
|
57
|
+
baseUrl: props.baseUrl,
|
|
58
|
+
tenantId: props.tenantId,
|
|
59
|
+
headers: {
|
|
60
|
+
// Note: cookies are sent automatically with fetch credentials: 'include'
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
throw new Error("Invalid SaferCityProvider configuration");
|
|
65
|
+
}, [props]);
|
|
66
|
+
const directModeTokenGetter = isDirectMode(props) ? props.getAccessToken : null;
|
|
67
|
+
react.useEffect(() => {
|
|
68
|
+
if (!directModeTokenGetter) return;
|
|
69
|
+
let isMounted = true;
|
|
70
|
+
const updateToken = async () => {
|
|
71
|
+
const token = await directModeTokenGetter();
|
|
72
|
+
if (isMounted) {
|
|
73
|
+
client.setToken(token);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
updateToken();
|
|
77
|
+
const interval = setInterval(updateToken, 3e4);
|
|
78
|
+
return () => {
|
|
79
|
+
isMounted = false;
|
|
80
|
+
clearInterval(interval);
|
|
81
|
+
};
|
|
82
|
+
}, [client, directModeTokenGetter]);
|
|
83
|
+
react.useEffect(() => {
|
|
84
|
+
if (mode !== "cookie") return;
|
|
85
|
+
if (!isCookieMode(props)) return;
|
|
86
|
+
let isMounted = true;
|
|
87
|
+
const checkSession = async () => {
|
|
88
|
+
try {
|
|
89
|
+
const response = await fetch(`${props.baseUrl}/v1/auth/session/status`, {
|
|
90
|
+
credentials: "include"
|
|
91
|
+
});
|
|
92
|
+
if (!isMounted) return;
|
|
93
|
+
if (response.ok) {
|
|
94
|
+
const data = await response.json();
|
|
95
|
+
setSession({
|
|
96
|
+
isAuthenticated: data.authenticated,
|
|
97
|
+
isLoading: false,
|
|
98
|
+
userId: data.userId,
|
|
99
|
+
tenantId: data.tenantId,
|
|
100
|
+
expiresAt: data.expiresAt
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
setSession({
|
|
104
|
+
isAuthenticated: false,
|
|
105
|
+
isLoading: false
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
if (!isMounted) return;
|
|
110
|
+
setSession({
|
|
111
|
+
isAuthenticated: false,
|
|
112
|
+
isLoading: false,
|
|
113
|
+
error: error instanceof Error ? error : new Error("Session check failed")
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
checkSession();
|
|
118
|
+
return () => {
|
|
119
|
+
isMounted = false;
|
|
120
|
+
};
|
|
121
|
+
}, [mode, props]);
|
|
122
|
+
const createSession = react.useCallback(async (token, tenantId) => {
|
|
123
|
+
if (mode !== "cookie" || !isCookieMode(props)) {
|
|
124
|
+
throw new Error("createSession is only available in cookie mode");
|
|
125
|
+
}
|
|
126
|
+
setSession((prev) => ({ ...prev, isLoading: true, error: void 0 }));
|
|
127
|
+
try {
|
|
128
|
+
const response = await fetch(`${props.baseUrl}/v1/auth/session`, {
|
|
129
|
+
method: "POST",
|
|
130
|
+
credentials: "include",
|
|
131
|
+
headers: {
|
|
132
|
+
"Content-Type": "application/json",
|
|
133
|
+
...tenantId && { "X-Tenant-ID": tenantId }
|
|
134
|
+
},
|
|
135
|
+
body: JSON.stringify({ token, tenantId })
|
|
136
|
+
});
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
const error = await response.json();
|
|
139
|
+
throw new Error(error.message || "Failed to create session");
|
|
140
|
+
}
|
|
141
|
+
const data = await response.json();
|
|
142
|
+
setSession({
|
|
143
|
+
isAuthenticated: true,
|
|
144
|
+
isLoading: false,
|
|
145
|
+
expiresAt: data.expiresAt,
|
|
146
|
+
tenantId
|
|
147
|
+
});
|
|
148
|
+
} catch (error) {
|
|
149
|
+
setSession({
|
|
150
|
+
isAuthenticated: false,
|
|
151
|
+
isLoading: false,
|
|
152
|
+
error: error instanceof Error ? error : new Error("Failed to create session")
|
|
153
|
+
});
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}, [mode, props]);
|
|
157
|
+
const clearSession = react.useCallback(async () => {
|
|
158
|
+
if (mode !== "cookie" || !isCookieMode(props)) {
|
|
159
|
+
throw new Error("clearSession is only available in cookie mode");
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
await fetch(`${props.baseUrl}/v1/auth/session/logout`, {
|
|
163
|
+
method: "POST",
|
|
164
|
+
credentials: "include"
|
|
165
|
+
});
|
|
166
|
+
} finally {
|
|
167
|
+
setSession({
|
|
168
|
+
isAuthenticated: false,
|
|
169
|
+
isLoading: false
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}, [mode, props]);
|
|
173
|
+
const refreshCsrf = react.useCallback(async () => {
|
|
174
|
+
if (mode !== "cookie" || !isCookieMode(props)) {
|
|
175
|
+
throw new Error("refreshCsrf is only available in cookie mode");
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
const response = await fetch(`${props.baseUrl}/v1/auth/session/refresh`, {
|
|
179
|
+
method: "POST",
|
|
180
|
+
credentials: "include"
|
|
181
|
+
});
|
|
182
|
+
if (response.ok) {
|
|
183
|
+
const data = await response.json();
|
|
184
|
+
return data.csrfToken;
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
}
|
|
188
|
+
return void 0;
|
|
189
|
+
}, [mode, props]);
|
|
23
190
|
const queryClient = react.useMemo(
|
|
24
191
|
() => externalQueryClient ?? new reactQuery.QueryClient({
|
|
25
192
|
defaultOptions: {
|
|
@@ -38,7 +205,14 @@ function SaferCityProvider({
|
|
|
38
205
|
}),
|
|
39
206
|
[externalQueryClient]
|
|
40
207
|
);
|
|
41
|
-
const contextValue = react.useMemo(() => ({
|
|
208
|
+
const contextValue = react.useMemo(() => ({
|
|
209
|
+
client,
|
|
210
|
+
mode,
|
|
211
|
+
session,
|
|
212
|
+
createSession,
|
|
213
|
+
clearSession,
|
|
214
|
+
refreshCsrf
|
|
215
|
+
}), [client, mode, session, createSession, clearSession, refreshCsrf]);
|
|
42
216
|
return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(SaferCityContext.Provider, { value: contextValue, children }) });
|
|
43
217
|
}
|
|
44
218
|
function useSaferCity() {
|
|
@@ -53,6 +227,23 @@ function useSaferCity() {
|
|
|
53
227
|
function useSaferCityClient() {
|
|
54
228
|
return useSaferCity().client;
|
|
55
229
|
}
|
|
230
|
+
function useSession() {
|
|
231
|
+
return useSaferCity().session;
|
|
232
|
+
}
|
|
233
|
+
function useAuthMode() {
|
|
234
|
+
return useSaferCity().mode;
|
|
235
|
+
}
|
|
236
|
+
function useSessionManager() {
|
|
237
|
+
const { createSession, clearSession, refreshCsrf, session } = useSaferCity();
|
|
238
|
+
return {
|
|
239
|
+
session,
|
|
240
|
+
createSession,
|
|
241
|
+
clearSession,
|
|
242
|
+
refreshCsrf,
|
|
243
|
+
isAuthenticated: session.isAuthenticated,
|
|
244
|
+
isLoading: session.isLoading
|
|
245
|
+
};
|
|
246
|
+
}
|
|
56
247
|
var saferCityKeys = {
|
|
57
248
|
all: ["safercity"],
|
|
58
249
|
// Health
|
|
@@ -471,6 +662,7 @@ function useStream(createStream, options = {}) {
|
|
|
471
662
|
|
|
472
663
|
exports.SaferCityProvider = SaferCityProvider;
|
|
473
664
|
exports.saferCityKeys = saferCityKeys;
|
|
665
|
+
exports.useAuthMode = useAuthMode;
|
|
474
666
|
exports.useCancelPanic = useCancelPanic;
|
|
475
667
|
exports.useCreatePanic = useCreatePanic;
|
|
476
668
|
exports.useCreateSubscription = useCreateSubscription;
|
|
@@ -486,6 +678,8 @@ exports.usePanicStream = usePanicStream;
|
|
|
486
678
|
exports.usePanics = usePanics;
|
|
487
679
|
exports.useSaferCity = useSaferCity;
|
|
488
680
|
exports.useSaferCityClient = useSaferCityClient;
|
|
681
|
+
exports.useSession = useSession;
|
|
682
|
+
exports.useSessionManager = useSessionManager;
|
|
489
683
|
exports.useStream = useStream;
|
|
490
684
|
exports.useSubscriptionStats = useSubscriptionStats;
|
|
491
685
|
exports.useSubscriptionTypes = useSubscriptionTypes;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.tsx","../src/hooks.ts","../src/use-stream.ts"],"names":["createContext","useMemo","createSaferCityClient","QueryClient","jsx","QueryClientProvider","useContext","useQuery","useQueryClient","useMutation","useState","useRef","useCallback","useEffect"],"mappings":"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","file":"index.cjs","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"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/hooks.ts","../src/use-stream.ts"],"names":["createContext","useMemo","useState","createSaferCityClient","useEffect","useCallback","QueryClient","jsx","QueryClientProvider","useContext","useQuery","useQueryClient","useMutation","useRef"],"mappings":"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","file":"index.cjs","sourcesContent":["'use client';\n\nimport { createContext, useContext, useMemo, useCallback, useState, useEffect, type ReactNode } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { createSaferCityClient, type SaferCityClient, type SaferCityClientOptions } from '@safercity/sdk';\nimport type { AuthMode, ProxyModeConfig, DirectModeConfig, CookieModeConfig } from '@safercity/sdk';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Session state for cookie-based auth\n */\nexport interface SessionState {\n isAuthenticated: boolean;\n isLoading: boolean;\n userId?: string;\n tenantId?: string;\n expiresAt?: number;\n error?: Error;\n}\n\n/**\n * Context value for SaferCity provider\n */\ninterface SaferCityContextValue {\n client: SaferCityClient;\n mode: AuthMode;\n session: SessionState;\n /** Create session from external JWT (cookie mode only) */\n createSession: (token: string, tenantId?: string) => Promise<void>;\n /** Clear current session (cookie mode only) */\n clearSession: () => Promise<void>;\n /** Refresh CSRF token (cookie mode only) */\n refreshCsrf: () => Promise<string | undefined>;\n}\n\nconst SaferCityContext = createContext<SaferCityContextValue | null>(null);\n\n// ============================================================================\n// Provider Props\n// ============================================================================\n\n/**\n * Base props for all modes\n */\ninterface BaseProviderProps {\n children: ReactNode;\n queryClient?: QueryClient;\n}\n\n/**\n * Props for proxy mode (DEFAULT)\n */\nexport interface ProxyModeProviderProps extends BaseProviderProps, ProxyModeConfig {}\n\n/**\n * Props for direct mode\n */\nexport interface DirectModeProviderProps extends BaseProviderProps, DirectModeConfig {}\n\n/**\n * Props for cookie mode\n */\nexport interface CookieModeProviderProps extends BaseProviderProps, CookieModeConfig {}\n\n/**\n * Legacy props (for backward compatibility)\n */\nexport interface LegacyProviderProps extends BaseProviderProps, SaferCityClientOptions {}\n\n/**\n * Combined props type\n */\nexport type SaferCityProviderProps = \n | ProxyModeProviderProps \n | DirectModeProviderProps \n | CookieModeProviderProps\n | LegacyProviderProps;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nfunction isProxyMode(props: SaferCityProviderProps): props is ProxyModeProviderProps {\n return !('mode' in props) || props.mode === 'proxy' || props.mode === undefined;\n}\n\nfunction isDirectMode(props: SaferCityProviderProps): props is DirectModeProviderProps {\n return 'mode' in props && props.mode === 'direct';\n}\n\nfunction isCookieMode(props: SaferCityProviderProps): props is CookieModeProviderProps {\n return 'mode' in props && props.mode === 'cookie';\n}\n\nfunction isLegacyMode(props: SaferCityProviderProps): props is LegacyProviderProps {\n return 'baseUrl' in props && 'token' in props && !('mode' in props);\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\n/**\n * Provider component for SaferCity SDK\n * \n * Supports three authentication modes:\n * \n * **Proxy Mode (Default)** - Most secure, recommended for production\n * ```tsx\n * <SaferCityProvider mode=\"proxy\" proxyBaseUrl=\"/api/safercity\">\n * <App />\n * </SaferCityProvider>\n * ```\n * \n * **Direct Mode** - For white-label apps with external auth\n * ```tsx\n * <SaferCityProvider\n * mode=\"direct\"\n * baseUrl=\"https://api.safercity.com\"\n * tenantId=\"tenant-123\"\n * getAccessToken={() => session?.accessToken}\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n * \n * **Cookie Mode** - For first-party web apps\n * ```tsx\n * <SaferCityProvider mode=\"cookie\" baseUrl=\"https://api.safercity.com\">\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport function SaferCityProvider(props: SaferCityProviderProps) {\n const { children, queryClient: externalQueryClient } = props;\n \n // Determine mode\n const mode: AuthMode = useMemo(() => {\n if (isDirectMode(props)) return 'direct';\n if (isCookieMode(props)) return 'cookie';\n return 'proxy';\n }, [props]);\n\n // Session state for cookie mode\n const [session, setSession] = useState<SessionState>({\n isAuthenticated: false,\n isLoading: mode === 'cookie',\n });\n\n // Create client based on mode\n const client = useMemo(() => {\n if (isLegacyMode(props)) {\n // Legacy mode - direct token\n return createSaferCityClient({\n baseUrl: props.baseUrl,\n token: props.token,\n tenantId: props.tenantId,\n fetch: props.fetch,\n timeout: props.timeout,\n headers: props.headers,\n });\n }\n\n if (isProxyMode(props)) {\n // Proxy mode - requests go through local proxy\n const proxyBaseUrl = props.proxyBaseUrl ?? '/api/safercity';\n return createSaferCityClient({\n baseUrl: proxyBaseUrl,\n });\n }\n\n if (isDirectMode(props)) {\n // Direct mode - use external token\n return createSaferCityClient({\n baseUrl: props.baseUrl,\n tenantId: props.tenantId,\n });\n }\n\n if (isCookieMode(props)) {\n // Cookie mode - credentials included automatically\n return createSaferCityClient({\n baseUrl: props.baseUrl,\n tenantId: props.tenantId,\n headers: {\n // Note: cookies are sent automatically with fetch credentials: 'include'\n },\n });\n }\n\n throw new Error('Invalid SaferCityProvider configuration');\n }, [props]);\n\n // Token getter for direct mode\n const directModeTokenGetter = isDirectMode(props) ? props.getAccessToken : null;\n\n // Update token for direct mode\n useEffect(() => {\n if (!directModeTokenGetter) return;\n\n let isMounted = true;\n \n const updateToken = async () => {\n const token = await directModeTokenGetter();\n if (isMounted) {\n client.setToken(token);\n }\n };\n\n updateToken();\n\n // Re-check token periodically\n const interval = setInterval(updateToken, 30000);\n return () => {\n isMounted = false;\n clearInterval(interval);\n };\n }, [client, directModeTokenGetter]);\n\n // Check session status for cookie mode\n useEffect(() => {\n if (mode !== 'cookie') return;\n if (!isCookieMode(props)) return;\n\n let isMounted = true;\n\n const checkSession = async () => {\n try {\n const response = await fetch(`${props.baseUrl}/v1/auth/session/status`, {\n credentials: 'include',\n });\n \n if (!isMounted) return;\n\n if (response.ok) {\n const data = await response.json();\n setSession({\n isAuthenticated: data.authenticated,\n isLoading: false,\n userId: data.userId,\n tenantId: data.tenantId,\n expiresAt: data.expiresAt,\n });\n } else {\n setSession({\n isAuthenticated: false,\n isLoading: false,\n });\n }\n } catch (error) {\n if (!isMounted) return;\n setSession({\n isAuthenticated: false,\n isLoading: false,\n error: error instanceof Error ? error : new Error('Session check failed'),\n });\n }\n };\n\n checkSession();\n\n return () => {\n isMounted = false;\n };\n }, [mode, props]);\n\n // Create session (cookie mode)\n const createSession = useCallback(async (token: string, tenantId?: string) => {\n if (mode !== 'cookie' || !isCookieMode(props)) {\n throw new Error('createSession is only available in cookie mode');\n }\n\n setSession(prev => ({ ...prev, isLoading: true, error: undefined }));\n\n try {\n const response = await fetch(`${props.baseUrl}/v1/auth/session`, {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...(tenantId && { 'X-Tenant-ID': tenantId }),\n },\n body: JSON.stringify({ token, tenantId }),\n });\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.message || 'Failed to create session');\n }\n\n const data = await response.json();\n \n setSession({\n isAuthenticated: true,\n isLoading: false,\n expiresAt: data.expiresAt,\n tenantId,\n });\n } catch (error) {\n setSession({\n isAuthenticated: false,\n isLoading: false,\n error: error instanceof Error ? error : new Error('Failed to create session'),\n });\n throw error;\n }\n }, [mode, props]);\n\n // Clear session (cookie mode)\n const clearSession = useCallback(async () => {\n if (mode !== 'cookie' || !isCookieMode(props)) {\n throw new Error('clearSession is only available in cookie mode');\n }\n\n try {\n await fetch(`${props.baseUrl}/v1/auth/session/logout`, {\n method: 'POST',\n credentials: 'include',\n });\n } finally {\n setSession({\n isAuthenticated: false,\n isLoading: false,\n });\n }\n }, [mode, props]);\n\n // Refresh CSRF token (cookie mode)\n const refreshCsrf = useCallback(async (): Promise<string | undefined> => {\n if (mode !== 'cookie' || !isCookieMode(props)) {\n throw new Error('refreshCsrf is only available in cookie mode');\n }\n\n try {\n const response = await fetch(`${props.baseUrl}/v1/auth/session/refresh`, {\n method: 'POST',\n credentials: 'include',\n });\n\n if (response.ok) {\n const data = await response.json();\n return data.csrfToken;\n }\n } catch {\n // Ignore errors\n }\n \n return undefined;\n }, [mode, props]);\n\n // Create 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(() => ({\n client,\n mode,\n session,\n createSession,\n clearSession,\n refreshCsrf,\n }), [client, mode, session, createSession, clearSession, refreshCsrf]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <SaferCityContext.Provider value={contextValue}>\n {children}\n </SaferCityContext.Provider>\n </QueryClientProvider>\n );\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Hook to access the full SaferCity context\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 the SaferCity client\n */\nexport function useSaferCityClient(): SaferCityClient {\n return useSaferCity().client;\n}\n\n/**\n * Hook to access session state (cookie mode)\n */\nexport function useSession(): SessionState {\n return useSaferCity().session;\n}\n\n/**\n * Hook to get the current auth mode\n */\nexport function useAuthMode(): AuthMode {\n return useSaferCity().mode;\n}\n\n/**\n * Hook to manage session (cookie mode)\n */\nexport function useSessionManager() {\n const { createSession, clearSession, refreshCsrf, session } = useSaferCity();\n \n return {\n session,\n createSession,\n clearSession,\n refreshCsrf,\n isAuthenticated: session.isAuthenticated,\n isLoading: session.isLoading,\n };\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/dist/index.d.cts
CHANGED
|
@@ -1,74 +1,125 @@
|
|
|
1
|
-
import { SaferCityClientOptions, SaferCityClient, ApiResponse, SaferCityApiError, ServerSentEvent } from '@safercity/sdk';
|
|
1
|
+
import { ProxyModeConfig, DirectModeConfig, CookieModeConfig, SaferCityClientOptions, SaferCityClient, AuthMode, ApiResponse, SaferCityApiError, ServerSentEvent } from '@safercity/sdk';
|
|
2
2
|
export * from '@safercity/sdk';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
5
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
6
6
|
import { QueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Session state for cookie-based auth
|
|
10
|
+
*/
|
|
11
|
+
interface SessionState {
|
|
12
|
+
isAuthenticated: boolean;
|
|
13
|
+
isLoading: boolean;
|
|
14
|
+
userId?: string;
|
|
15
|
+
tenantId?: string;
|
|
16
|
+
expiresAt?: number;
|
|
17
|
+
error?: Error;
|
|
18
|
+
}
|
|
8
19
|
/**
|
|
9
20
|
* Context value for SaferCity provider
|
|
10
21
|
*/
|
|
11
22
|
interface SaferCityContextValue {
|
|
12
23
|
client: SaferCityClient;
|
|
24
|
+
mode: AuthMode;
|
|
25
|
+
session: SessionState;
|
|
26
|
+
/** Create session from external JWT (cookie mode only) */
|
|
27
|
+
createSession: (token: string, tenantId?: string) => Promise<void>;
|
|
28
|
+
/** Clear current session (cookie mode only) */
|
|
29
|
+
clearSession: () => Promise<void>;
|
|
30
|
+
/** Refresh CSRF token (cookie mode only) */
|
|
31
|
+
refreshCsrf: () => Promise<string | undefined>;
|
|
13
32
|
}
|
|
14
33
|
/**
|
|
15
|
-
*
|
|
34
|
+
* Base props for all modes
|
|
16
35
|
*/
|
|
17
|
-
interface
|
|
36
|
+
interface BaseProviderProps {
|
|
18
37
|
children: ReactNode;
|
|
19
|
-
/**
|
|
20
|
-
* Custom QueryClient instance (optional)
|
|
21
|
-
* If not provided, a new QueryClient will be created
|
|
22
|
-
*/
|
|
23
38
|
queryClient?: QueryClient;
|
|
24
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Props for proxy mode (DEFAULT)
|
|
42
|
+
*/
|
|
43
|
+
interface ProxyModeProviderProps extends BaseProviderProps, ProxyModeConfig {
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Props for direct mode
|
|
47
|
+
*/
|
|
48
|
+
interface DirectModeProviderProps extends BaseProviderProps, DirectModeConfig {
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Props for cookie mode
|
|
52
|
+
*/
|
|
53
|
+
interface CookieModeProviderProps extends BaseProviderProps, CookieModeConfig {
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Legacy props (for backward compatibility)
|
|
57
|
+
*/
|
|
58
|
+
interface LegacyProviderProps extends BaseProviderProps, SaferCityClientOptions {
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Combined props type
|
|
62
|
+
*/
|
|
63
|
+
type SaferCityProviderProps = ProxyModeProviderProps | DirectModeProviderProps | CookieModeProviderProps | LegacyProviderProps;
|
|
25
64
|
/**
|
|
26
65
|
* Provider component for SaferCity SDK
|
|
27
66
|
*
|
|
28
|
-
*
|
|
67
|
+
* Supports three authentication modes:
|
|
29
68
|
*
|
|
30
|
-
*
|
|
69
|
+
* **Proxy Mode (Default)** - Most secure, recommended for production
|
|
31
70
|
* ```tsx
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* return (
|
|
36
|
-
* <SaferCityProvider
|
|
37
|
-
* baseUrl="https://api.safercity.com"
|
|
38
|
-
* token={userToken}
|
|
39
|
-
* tenantId="tenant-123"
|
|
40
|
-
* >
|
|
41
|
-
* <YourApp />
|
|
42
|
-
* </SaferCityProvider>
|
|
43
|
-
* );
|
|
44
|
-
* }
|
|
71
|
+
* <SaferCityProvider mode="proxy" proxyBaseUrl="/api/safercity">
|
|
72
|
+
* <App />
|
|
73
|
+
* </SaferCityProvider>
|
|
45
74
|
* ```
|
|
46
|
-
*/
|
|
47
|
-
declare function SaferCityProvider({ children, queryClient: externalQueryClient, ...clientOptions }: SaferCityProviderProps): react_jsx_runtime.JSX.Element;
|
|
48
|
-
/**
|
|
49
|
-
* Hook to access the SaferCity client
|
|
50
|
-
*
|
|
51
|
-
* Must be used within a SaferCityProvider.
|
|
52
75
|
*
|
|
53
|
-
*
|
|
76
|
+
* **Direct Mode** - For white-label apps with external auth
|
|
54
77
|
* ```tsx
|
|
55
|
-
*
|
|
56
|
-
*
|
|
78
|
+
* <SaferCityProvider
|
|
79
|
+
* mode="direct"
|
|
80
|
+
* baseUrl="https://api.safercity.com"
|
|
81
|
+
* tenantId="tenant-123"
|
|
82
|
+
* getAccessToken={() => session?.accessToken}
|
|
83
|
+
* >
|
|
84
|
+
* <App />
|
|
85
|
+
* </SaferCityProvider>
|
|
86
|
+
* ```
|
|
57
87
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
88
|
+
* **Cookie Mode** - For first-party web apps
|
|
89
|
+
* ```tsx
|
|
90
|
+
* <SaferCityProvider mode="cookie" baseUrl="https://api.safercity.com">
|
|
91
|
+
* <App />
|
|
92
|
+
* </SaferCityProvider>
|
|
63
93
|
* ```
|
|
64
94
|
*/
|
|
95
|
+
declare function SaferCityProvider(props: SaferCityProviderProps): react_jsx_runtime.JSX.Element;
|
|
96
|
+
/**
|
|
97
|
+
* Hook to access the full SaferCity context
|
|
98
|
+
*/
|
|
65
99
|
declare function useSaferCity(): SaferCityContextValue;
|
|
66
100
|
/**
|
|
67
|
-
* Hook to access
|
|
68
|
-
*
|
|
69
|
-
* Convenience wrapper around useSaferCity().
|
|
101
|
+
* Hook to access the SaferCity client
|
|
70
102
|
*/
|
|
71
103
|
declare function useSaferCityClient(): SaferCityClient;
|
|
104
|
+
/**
|
|
105
|
+
* Hook to access session state (cookie mode)
|
|
106
|
+
*/
|
|
107
|
+
declare function useSession(): SessionState;
|
|
108
|
+
/**
|
|
109
|
+
* Hook to get the current auth mode
|
|
110
|
+
*/
|
|
111
|
+
declare function useAuthMode(): AuthMode;
|
|
112
|
+
/**
|
|
113
|
+
* Hook to manage session (cookie mode)
|
|
114
|
+
*/
|
|
115
|
+
declare function useSessionManager(): {
|
|
116
|
+
session: SessionState;
|
|
117
|
+
createSession: (token: string, tenantId?: string) => Promise<void>;
|
|
118
|
+
clearSession: () => Promise<void>;
|
|
119
|
+
refreshCsrf: () => Promise<string | undefined>;
|
|
120
|
+
isAuthenticated: boolean;
|
|
121
|
+
isLoading: boolean;
|
|
122
|
+
};
|
|
72
123
|
|
|
73
124
|
declare const saferCityKeys: {
|
|
74
125
|
all: readonly ["safercity"];
|
|
@@ -568,4 +619,4 @@ declare function useStream<T = ServerSentEvent>(createStream: () => AsyncIterabl
|
|
|
568
619
|
error: Error | null;
|
|
569
620
|
};
|
|
570
621
|
|
|
571
|
-
export { SaferCityProvider, type SaferCityProviderProps, type StreamState, type UseStreamOptions, 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 };
|
|
622
|
+
export { type CookieModeProviderProps, type DirectModeProviderProps, type ProxyModeProviderProps, SaferCityProvider, type SaferCityProviderProps, type SessionState, type StreamState, type UseStreamOptions, saferCityKeys, useAuthMode, useCancelPanic, useCreatePanic, useCreateSubscription, useCreateUser, useCrimeCategories, useCrimeTypes, useCrimes, useDeleteUser, useHealthCheck, useLocationSafety, usePanic, usePanicStream, usePanics, useSaferCity, useSaferCityClient, useSession, useSessionManager, useStream, useSubscriptionStats, useSubscriptionTypes, useSubscriptions, useUpdatePanicLocation, useUpdateUser, useUser, useUsers, useWhoAmI };
|