@growsober/sdk 1.0.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/README.md +276 -0
- package/dist/__tests__/e2e.test.d.ts +7 -0
- package/dist/__tests__/e2e.test.js +472 -0
- package/dist/api/client.d.ts +11 -0
- package/dist/api/client.js +61 -0
- package/dist/api/mutations/admin.d.ts +167 -0
- package/dist/api/mutations/admin.js +326 -0
- package/dist/api/mutations/ambassadors.d.ts +52 -0
- package/dist/api/mutations/ambassadors.js +148 -0
- package/dist/api/mutations/auth.d.ts +267 -0
- package/dist/api/mutations/auth.js +332 -0
- package/dist/api/mutations/bookings.d.ts +59 -0
- package/dist/api/mutations/bookings.js +143 -0
- package/dist/api/mutations/event-chat.d.ts +35 -0
- package/dist/api/mutations/event-chat.js +147 -0
- package/dist/api/mutations/events.d.ts +87 -0
- package/dist/api/mutations/events.js +205 -0
- package/dist/api/mutations/grow90.d.ts +36 -0
- package/dist/api/mutations/grow90.js +132 -0
- package/dist/api/mutations/hubs.d.ts +111 -0
- package/dist/api/mutations/hubs.js +240 -0
- package/dist/api/mutations/index.d.ts +22 -0
- package/dist/api/mutations/index.js +39 -0
- package/dist/api/mutations/jack.d.ts +61 -0
- package/dist/api/mutations/jack.js +104 -0
- package/dist/api/mutations/library.d.ts +67 -0
- package/dist/api/mutations/library.js +168 -0
- package/dist/api/mutations/map.d.ts +153 -0
- package/dist/api/mutations/map.js +181 -0
- package/dist/api/mutations/matching.d.ts +130 -0
- package/dist/api/mutations/matching.js +204 -0
- package/dist/api/mutations/notifications.d.ts +63 -0
- package/dist/api/mutations/notifications.js +106 -0
- package/dist/api/mutations/offers.d.ts +26 -0
- package/dist/api/mutations/offers.js +47 -0
- package/dist/api/mutations/subscriptions.d.ts +127 -0
- package/dist/api/mutations/subscriptions.js +140 -0
- package/dist/api/mutations/support.d.ts +165 -0
- package/dist/api/mutations/support.js +307 -0
- package/dist/api/mutations/users.d.ts +211 -0
- package/dist/api/mutations/users.js +261 -0
- package/dist/api/queries/admin.d.ts +257 -0
- package/dist/api/queries/admin.js +320 -0
- package/dist/api/queries/ambassadors.d.ts +53 -0
- package/dist/api/queries/ambassadors.js +98 -0
- package/dist/api/queries/auth.d.ts +16 -0
- package/dist/api/queries/auth.js +25 -0
- package/dist/api/queries/bookings.d.ts +91 -0
- package/dist/api/queries/bookings.js +102 -0
- package/dist/api/queries/businesses.d.ts +212 -0
- package/dist/api/queries/businesses.js +154 -0
- package/dist/api/queries/event-chat.d.ts +19 -0
- package/dist/api/queries/event-chat.js +75 -0
- package/dist/api/queries/events.d.ts +322 -0
- package/dist/api/queries/events.js +221 -0
- package/dist/api/queries/grow90.d.ts +26 -0
- package/dist/api/queries/grow90.js +85 -0
- package/dist/api/queries/hubs.d.ts +165 -0
- package/dist/api/queries/hubs.js +143 -0
- package/dist/api/queries/index.d.ts +23 -0
- package/dist/api/queries/index.js +40 -0
- package/dist/api/queries/jack.d.ts +63 -0
- package/dist/api/queries/jack.js +92 -0
- package/dist/api/queries/library.d.ts +132 -0
- package/dist/api/queries/library.js +120 -0
- package/dist/api/queries/map.d.ts +216 -0
- package/dist/api/queries/map.js +278 -0
- package/dist/api/queries/matching.d.ts +136 -0
- package/dist/api/queries/matching.js +161 -0
- package/dist/api/queries/notifications.d.ts +78 -0
- package/dist/api/queries/notifications.js +88 -0
- package/dist/api/queries/offers.d.ts +91 -0
- package/dist/api/queries/offers.js +103 -0
- package/dist/api/queries/subscriptions.d.ts +56 -0
- package/dist/api/queries/subscriptions.js +73 -0
- package/dist/api/queries/support.d.ts +106 -0
- package/dist/api/queries/support.js +202 -0
- package/dist/api/queries/users.d.ts +293 -0
- package/dist/api/queries/users.js +370 -0
- package/dist/api/types.d.ts +464 -0
- package/dist/api/types.js +9 -0
- package/dist/hooks/useAuth.d.ts +5 -0
- package/dist/hooks/useAuth.js +39 -0
- package/dist/hooks/useUser.d.ts +43 -0
- package/dist/hooks/useUser.js +44 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +67 -0
- package/package.json +62 -0
- package/src/__tests__/e2e.test.ts +502 -0
- package/src/api/client.ts +71 -0
- package/src/api/mutations/admin.ts +531 -0
- package/src/api/mutations/ambassadors.ts +185 -0
- package/src/api/mutations/auth.ts +350 -0
- package/src/api/mutations/bookings.ts +190 -0
- package/src/api/mutations/event-chat.ts +177 -0
- package/src/api/mutations/events.ts +273 -0
- package/src/api/mutations/grow90.ts +169 -0
- package/src/api/mutations/hubs.ts +385 -0
- package/src/api/mutations/index.ts +23 -0
- package/src/api/mutations/jack.ts +130 -0
- package/src/api/mutations/library.ts +212 -0
- package/src/api/mutations/map.ts +230 -0
- package/src/api/mutations/matching.ts +271 -0
- package/src/api/mutations/notifications.ts +114 -0
- package/src/api/mutations/offers.ts +73 -0
- package/src/api/mutations/subscriptions.ts +162 -0
- package/src/api/mutations/support.ts +390 -0
- package/src/api/mutations/users.ts +271 -0
- package/src/api/queries/admin.ts +480 -0
- package/src/api/queries/ambassadors.ts +139 -0
- package/src/api/queries/auth.ts +24 -0
- package/src/api/queries/bookings.ts +135 -0
- package/src/api/queries/businesses.ts +203 -0
- package/src/api/queries/event-chat.ts +78 -0
- package/src/api/queries/events.ts +272 -0
- package/src/api/queries/grow90.ts +98 -0
- package/src/api/queries/hubs.ts +211 -0
- package/src/api/queries/index.ts +24 -0
- package/src/api/queries/jack.ts +127 -0
- package/src/api/queries/library.ts +166 -0
- package/src/api/queries/map.ts +331 -0
- package/src/api/queries/matching.ts +238 -0
- package/src/api/queries/notifications.ts +103 -0
- package/src/api/queries/offers.ts +136 -0
- package/src/api/queries/subscriptions.ts +91 -0
- package/src/api/queries/support.ts +235 -0
- package/src/api/queries/users.ts +393 -0
- package/src/api/types.ts +596 -0
- package/src/index.ts +57 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
2
|
+
import type { AmbassadorResponse, ApplyAmbassadorRequest, UpdateAmbassadorRequest } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Apply to become an ambassador
|
|
5
|
+
*/
|
|
6
|
+
export declare function useApplyAmbassador(options?: Omit<UseMutationOptions<AmbassadorResponse, Error, ApplyAmbassadorRequest>, 'mutationFn'>): UseMutationResult<AmbassadorResponse, Error, ApplyAmbassadorRequest>;
|
|
7
|
+
/**
|
|
8
|
+
* Update own ambassador profile
|
|
9
|
+
*/
|
|
10
|
+
export declare function useUpdateMyAmbassador(options?: Omit<UseMutationOptions<AmbassadorResponse, Error, Partial<UpdateAmbassadorRequest>>, 'mutationFn'>): UseMutationResult<AmbassadorResponse, Error, Partial<UpdateAmbassadorRequest>>;
|
|
11
|
+
/**
|
|
12
|
+
* Update ambassador (admin)
|
|
13
|
+
*/
|
|
14
|
+
export declare function useUpdateAmbassador(options?: Omit<UseMutationOptions<AmbassadorResponse, Error, {
|
|
15
|
+
id: string;
|
|
16
|
+
data: UpdateAmbassadorRequest;
|
|
17
|
+
}>, 'mutationFn'>): UseMutationResult<AmbassadorResponse, Error, {
|
|
18
|
+
id: string;
|
|
19
|
+
data: UpdateAmbassadorRequest;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Approve ambassador application (admin)
|
|
23
|
+
*/
|
|
24
|
+
export declare function useApproveAmbassador(options?: Omit<UseMutationOptions<AmbassadorResponse, Error, string>, 'mutationFn'>): UseMutationResult<AmbassadorResponse, Error, string>;
|
|
25
|
+
/**
|
|
26
|
+
* Reject ambassador application (admin)
|
|
27
|
+
*/
|
|
28
|
+
export declare function useRejectAmbassador(options?: Omit<UseMutationOptions<{
|
|
29
|
+
success: boolean;
|
|
30
|
+
}, Error, string>, 'mutationFn'>): UseMutationResult<{
|
|
31
|
+
success: boolean;
|
|
32
|
+
}, Error, string>;
|
|
33
|
+
/**
|
|
34
|
+
* Deactivate ambassador (admin)
|
|
35
|
+
*/
|
|
36
|
+
export declare function useDeactivateAmbassador(options?: Omit<UseMutationOptions<AmbassadorResponse, Error, string>, 'mutationFn'>): UseMutationResult<AmbassadorResponse, Error, string>;
|
|
37
|
+
/**
|
|
38
|
+
* Add reward points to ambassador (admin)
|
|
39
|
+
*/
|
|
40
|
+
export declare function useAddAmbassadorReward(options?: Omit<UseMutationOptions<{
|
|
41
|
+
success: boolean;
|
|
42
|
+
}, Error, {
|
|
43
|
+
id: string;
|
|
44
|
+
points: number;
|
|
45
|
+
reason?: string;
|
|
46
|
+
}>, 'mutationFn'>): UseMutationResult<{
|
|
47
|
+
success: boolean;
|
|
48
|
+
}, Error, {
|
|
49
|
+
id: string;
|
|
50
|
+
points: number;
|
|
51
|
+
reason?: string;
|
|
52
|
+
}>;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useApplyAmbassador = useApplyAmbassador;
|
|
4
|
+
exports.useUpdateMyAmbassador = useUpdateMyAmbassador;
|
|
5
|
+
exports.useUpdateAmbassador = useUpdateAmbassador;
|
|
6
|
+
exports.useApproveAmbassador = useApproveAmbassador;
|
|
7
|
+
exports.useRejectAmbassador = useRejectAmbassador;
|
|
8
|
+
exports.useDeactivateAmbassador = useDeactivateAmbassador;
|
|
9
|
+
exports.useAddAmbassadorReward = useAddAmbassadorReward;
|
|
10
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
11
|
+
const client_1 = require("../client");
|
|
12
|
+
const ambassadors_1 = require("../queries/ambassadors");
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// MUTATION HOOKS
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Apply to become an ambassador
|
|
18
|
+
*/
|
|
19
|
+
function useApplyAmbassador(options) {
|
|
20
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
21
|
+
return (0, react_query_1.useMutation)({
|
|
22
|
+
mutationFn: async (data) => {
|
|
23
|
+
const client = (0, client_1.getApiClient)();
|
|
24
|
+
const response = await client.post('/api/v1/ambassadors/apply', data);
|
|
25
|
+
return response.data;
|
|
26
|
+
},
|
|
27
|
+
onSuccess: (ambassador) => {
|
|
28
|
+
queryClient.setQueryData(ambassadors_1.ambassadorKeys.me(), ambassador);
|
|
29
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.lists() });
|
|
30
|
+
},
|
|
31
|
+
...options,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Update own ambassador profile
|
|
36
|
+
*/
|
|
37
|
+
function useUpdateMyAmbassador(options) {
|
|
38
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
39
|
+
return (0, react_query_1.useMutation)({
|
|
40
|
+
mutationFn: async (data) => {
|
|
41
|
+
const client = (0, client_1.getApiClient)();
|
|
42
|
+
const response = await client.put('/api/v1/ambassadors/me', data);
|
|
43
|
+
return response.data;
|
|
44
|
+
},
|
|
45
|
+
onSuccess: (ambassador) => {
|
|
46
|
+
queryClient.setQueryData(ambassadors_1.ambassadorKeys.me(), ambassador);
|
|
47
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.lists() });
|
|
48
|
+
},
|
|
49
|
+
...options,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Update ambassador (admin)
|
|
54
|
+
*/
|
|
55
|
+
function useUpdateAmbassador(options) {
|
|
56
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
57
|
+
return (0, react_query_1.useMutation)({
|
|
58
|
+
mutationFn: async ({ id, data }) => {
|
|
59
|
+
const client = (0, client_1.getApiClient)();
|
|
60
|
+
const response = await client.put(`/api/v1/ambassadors/${id}`, data);
|
|
61
|
+
return response.data;
|
|
62
|
+
},
|
|
63
|
+
onSuccess: (ambassador, { id }) => {
|
|
64
|
+
queryClient.setQueryData(ambassadors_1.ambassadorKeys.detail(id), ambassador);
|
|
65
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.lists() });
|
|
66
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.pending() });
|
|
67
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.leaderboard() });
|
|
68
|
+
},
|
|
69
|
+
...options,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Approve ambassador application (admin)
|
|
74
|
+
*/
|
|
75
|
+
function useApproveAmbassador(options) {
|
|
76
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
77
|
+
return (0, react_query_1.useMutation)({
|
|
78
|
+
mutationFn: async (id) => {
|
|
79
|
+
const client = (0, client_1.getApiClient)();
|
|
80
|
+
const response = await client.post(`/api/v1/ambassadors/${id}/approve`);
|
|
81
|
+
return response.data;
|
|
82
|
+
},
|
|
83
|
+
onSuccess: (ambassador, id) => {
|
|
84
|
+
queryClient.setQueryData(ambassadors_1.ambassadorKeys.detail(id), ambassador);
|
|
85
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.lists() });
|
|
86
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.pending() });
|
|
87
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.leaderboard() });
|
|
88
|
+
},
|
|
89
|
+
...options,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Reject ambassador application (admin)
|
|
94
|
+
*/
|
|
95
|
+
function useRejectAmbassador(options) {
|
|
96
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
97
|
+
return (0, react_query_1.useMutation)({
|
|
98
|
+
mutationFn: async (id) => {
|
|
99
|
+
const client = (0, client_1.getApiClient)();
|
|
100
|
+
const response = await client.post(`/api/v1/ambassadors/${id}/reject`);
|
|
101
|
+
return response.data;
|
|
102
|
+
},
|
|
103
|
+
onSuccess: (_, id) => {
|
|
104
|
+
queryClient.removeQueries({ queryKey: ambassadors_1.ambassadorKeys.detail(id) });
|
|
105
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.lists() });
|
|
106
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.pending() });
|
|
107
|
+
},
|
|
108
|
+
...options,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Deactivate ambassador (admin)
|
|
113
|
+
*/
|
|
114
|
+
function useDeactivateAmbassador(options) {
|
|
115
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
116
|
+
return (0, react_query_1.useMutation)({
|
|
117
|
+
mutationFn: async (id) => {
|
|
118
|
+
const client = (0, client_1.getApiClient)();
|
|
119
|
+
const response = await client.post(`/api/v1/ambassadors/${id}/deactivate`);
|
|
120
|
+
return response.data;
|
|
121
|
+
},
|
|
122
|
+
onSuccess: (ambassador, id) => {
|
|
123
|
+
queryClient.setQueryData(ambassadors_1.ambassadorKeys.detail(id), ambassador);
|
|
124
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.lists() });
|
|
125
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.leaderboard() });
|
|
126
|
+
},
|
|
127
|
+
...options,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Add reward points to ambassador (admin)
|
|
132
|
+
*/
|
|
133
|
+
function useAddAmbassadorReward(options) {
|
|
134
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
135
|
+
return (0, react_query_1.useMutation)({
|
|
136
|
+
mutationFn: async ({ id, points, reason }) => {
|
|
137
|
+
const client = (0, client_1.getApiClient)();
|
|
138
|
+
const response = await client.post(`/api/v1/ambassadors/${id}/reward`, { points, reason });
|
|
139
|
+
return response.data;
|
|
140
|
+
},
|
|
141
|
+
onSuccess: (_, { id }) => {
|
|
142
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.detail(id) });
|
|
143
|
+
queryClient.invalidateQueries({ queryKey: ambassadors_1.ambassadorKeys.leaderboard() });
|
|
144
|
+
},
|
|
145
|
+
...options,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW1iYXNzYWRvcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL211dGF0aW9ucy9hbWJhc3NhZG9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWlCQSxnREFvQkM7QUFLRCxzREFvQkM7QUFLRCxrREFzQkM7QUFLRCxvREFtQkM7QUFLRCxrREFrQkM7QUFLRCwwREFrQkM7QUFLRCx3REFvQkM7QUF4TEQsdURBSytCO0FBQy9CLHNDQUF5QztBQUV6Qyx3REFBd0Q7QUFFeEQsK0VBQStFO0FBQy9FLGlCQUFpQjtBQUNqQiwrRUFBK0U7QUFFL0U7O0dBRUc7QUFDSCxTQUFnQixrQkFBa0IsQ0FDaEMsT0FHQztJQUVELE1BQU0sV0FBVyxHQUFHLElBQUEsNEJBQWMsR0FBRSxDQUFDO0lBRXJDLE9BQU8sSUFBQSx5QkFBVyxFQUFDO1FBQ2pCLFVBQVUsRUFBRSxLQUFLLEVBQUUsSUFBNEIsRUFBK0IsRUFBRTtZQUM5RSxNQUFNLE1BQU0sR0FBRyxJQUFBLHFCQUFZLEdBQUUsQ0FBQztZQUM5QixNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDdEUsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDO1FBQ3ZCLENBQUM7UUFDRCxTQUFTLEVBQUUsQ0FBQyxVQUFVLEVBQUUsRUFBRTtZQUN4QixXQUFXLENBQUMsWUFBWSxDQUFDLDRCQUFjLENBQUMsRUFBRSxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDMUQsV0FBVyxDQUFDLGlCQUFpQixDQUFDLEVBQUUsUUFBUSxFQUFFLDRCQUFjLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7UUFDRCxHQUFHLE9BQU87S0FDWCxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixxQkFBcUIsQ0FDbkMsT0FHQztJQUVELE1BQU0sV0FBVyxHQUFHLElB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UUFDdkIsQ0FBQztRQUNELFNBQVMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7WUFDdkIsV0FBVyxDQUFDLGlCQUFpQixDQUFDLEVBQUUsUUFBUSxFQUFFLDRCQUFjLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN2RSxXQUFXLENBQUMsaUJBQWlCLENBQUMsRUFBRSxRQUFRLEVBQUUsNEJBQWMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDNUUsQ0FBQztRQUNELEdBQUcsT0FBTztLQUNYLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICB1c2VNdXRhdGlvbixcbiAgdXNlUXVlcnlDbGllbnQsXG4gIFVzZU11dGF0aW9uT3B0aW9ucyxcbiAgVXNlTXV0YXRpb25SZXN1bHQsXG59IGZyb20gJ0B0YW5zdGFjay9yZWFjdC1xdWVyeSc7XG5pbXBvcnQgeyBnZXRBcGlDbGllbnQgfSBmcm9tICcuLi9jbGllbnQnO1xuaW1wb3J0IHR5cGUgeyBBbWJhc3NhZG9yUmVzcG9uc2UsIEFwcGx5QW1iYXNzYWRvclJlcXVlc3QsIFVwZGF0ZUFtYmFzc2Fkb3JSZXF1ZXN0IH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgYW1iYXNzYWRvcktleXMgfSBmcm9tICcuLi9xdWVyaWVzL2FtYmFzc2Fkb3JzJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gTVVUQVRJT04gSE9PS1Ncbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBBcHBseSB0byBiZWNvbWUgYW4gYW1iYXNzYWRvclxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlQXBwbHlBbWJhc3NhZG9yKFxuICBvcHRpb25zPzogT21pdDxcbiAgICBVc2VNdXRhdGlvbk9wdGlvbnM8QW1iYXNzYWRvclJlc3BvbnNlLCBFcnJvciwgQXBwbHlBbWJhc3NhZG9yUmVxdWVzdD4sXG4gICAgJ211dGF0aW9uRm4nXG4gID5cbik6IFVzZU11dGF0aW9uUmVzdWx0PEFtYmFzc2Fkb3JSZXNwb25zZSwgRXJyb3IsIEFwcGx5QW1iYXNzYWRvclJlcXVlc3Q+IHtcbiAgY29uc3QgcXVlcnlDbGllbnQgPSB1c2VRdWVyeUNsaWVudCgpO1xuXG4gIHJldHVybiB1c2VNdXRhdGlvbih7XG4gICAgbXV0YXRpb25GbjogYXN5bmMgKGRhdGE6IEFwcGx5QW1iYXNzYWRvclJlcXVlc3QpOiBQcm9taXNlPEFtYmFzc2Fkb3JSZXNwb25zZT4gPT4ge1xuICAgICAgY29uc3QgY2xpZW50ID0gZ2V0QXBpQ2xpZW50KCk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5wb3N0KCcvYXBpL3YxL2FtYmFzc2Fkb3JzL2FwcGx5JywgZGF0YSk7XG4gICAgICByZXR1cm4gcmVzcG9uc2UuZGF0YTtcbiAgICB9LFxuICAgIG9uU3VjY2VzczogKGFtYmFzc2Fkb3IpID0+IHtcbiAgICAgIHF1ZXJ5Q2xpZW50LnNldFF1ZXJ5RGF0YShhbWJhc3NhZG9yS2V5cy5tZSgpLCBhbWJhc3NhZG9yKTtcbiAgICAgIHF1ZXJ5Q2xpZW50LmludmFsaWRhdGVRdWVyaWVzKHsgcXVlcnlLZXk6IGFtYmFzc2Fkb3JLZXlzLmxpc3RzKCkgfSk7XG4gICAgfSxcbiAgICAuLi5vcHRpb25zLFxuICB9KTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgb3duIGFtYmFzc2Fkb3IgcHJvZmlsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlVXBkYXRlTXlBbWJhc3NhZG9yKFxuICBvcHRpb25zPzogT21pdDxcbiAgICBVc2VNdXRhdGlvbk9wdGlvbnM8QW1iYXNzYWRvclJlc3BvbnNlLCBFcnJvciwgUGFydGlhbDxVcGRhdGVBbWJhc3NhZG9yUmVxdWVzdD4+LFxuICAgICdtdXRhdGlvbkZuJ1xuICA+XG4pOiBVc2VNdXRhdGlvblJlc3VsdDxBbWJhc3NhZG9yUmVzcG9uc2UsIEVycm9yLCBQYXJ0aWFsPFVwZGF0ZUFtYmFzc2Fkb3JSZXF1ZXN0Pj4ge1xuICBjb25zdCBxdWVyeUNsaWVudCA9IHVzZVF1ZXJ5Q2xpZW50KCk7XG5cbiAgcmV0dXJuIHVzZU11dGF0aW9uKHtcbiAgICBtdXRhdGlvbkZuOiBhc3luYyAoZGF0YTogUGFydGlhbDxVcGRhdGVBbWJhc3NhZG9yUmVxdWVzdD4pOiBQcm9taXNlPEFtYmFzc2Fkb3JSZXNwb25zZT4gPT4ge1xuICAgICAgY29uc3QgY2xpZW50ID0gZ2V0QXBpQ2xpZW50KCk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5wdXQoJy9hcGkvdjEvYW1iYXNzYWRvcnMvbWUnLCBkYXRhKTtcbiAgICAgIHJldHVybiByZXNwb25zZS5kYXRhO1xuICAgIH0sXG4gICAgb25TdWNjZXNzOiAoYW1iYXNzYWRvcikgPT4ge1xuICAgICAgcXVlcnlDbGllbnQuc2V0UXVlcnlEYXRhKGFtYmFzc2Fkb3JLZXlzLm1lKCksIGFtYmFzc2Fkb3IpO1xuICAgICAgcXVlcnlDbGllbnQuaW52YWxpZGF0ZVF1ZXJpZXMoeyBxdWVyeUtleTogYW1iYXNzYWRvcktleXMubGlzdHMoKSB9KTtcbiAgICB9LFxuICAgIC4uLm9wdGlvbnMsXG4gIH0pO1xufVxuXG4vKipcbiAqIFVwZGF0ZSBhbWJhc3NhZG9yIChhZG1pbilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVVwZGF0ZUFtYmFzc2Fkb3IoXG4gIG9wdGlvbnM/OiBPbWl0PFxuICAgIFVzZU11dGF0aW9uT3B0aW9uczxBbWJhc3NhZG9yUmVzcG9uc2UsIEVycm9yLCB7IGlkOiBzdHJpbmc7IGRhdGE6IFVwZGF0ZUFtYmFzc2Fkb3JSZXF1ZXN0IH0+LFxuICAgICdtdXRhdGlvbkZuJ1xuICA+XG4pOiBVc2VNdXRhdGlvblJlc3VsdDxBbWJhc3NhZG9yUmVzcG9uc2UsIEVycm9yLCB7IGlkOiBzdHJpbmc7IGRhdGE6IFVwZGF0ZUFtYmFzc2Fkb3JSZXF1ZXN0IH0+IHtcbiAgY29uc3QgcXVlcnlDbGllbnQgPSB1c2VRdWVyeUNsaWVudCgpO1xuXG4gIHJldHVybiB1c2VNdXRhdGlvbih7XG4gICAgbXV0YXRpb25GbjogYXN5bmMgKHsgaWQsIGRhdGEgfSk6IFByb21pc2U8QW1iYXNzYWRvclJlc3BvbnNlPiA9PiB7XG4gICAgICBjb25zdCBjbGllbnQgPSBnZXRBcGlDbGllbnQoKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LnB1dChgL2FwaS92MS9hbWJhc3NhZG9ycy8ke2lkfWAsIGRhdGEpO1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE7XG4gICAgfSxcbiAgICBvblN1Y2Nlc3M6IChhbWJhc3NhZG9yLCB7IGlkIH0pID0+IHtcbiAgICAgIHF1ZXJ5Q2xpZW50LnNldFF1ZXJ5RGF0YShhbWJhc3NhZG9yS2V5cy5kZXRhaWwoaWQpLCBhbWJhc3NhZG9yKTtcbiAgICAgIHF1ZXJ5Q2xpZW50LmludmFsaWRhdGVRdWVyaWVzKHsgcXVlcnlLZXk6IGFtYmFzc2Fkb3JLZXlzLmxpc3RzKCkgfSk7XG4gICAgICBxdWVyeUNsaWVudC5pbnZhbGlkYXRlUXVlcmllcyh7IHF1ZXJ5S2V5OiBhbWJhc3NhZG9yS2V5cy5wZW5kaW5nKCkgfSk7XG4gICAgICBxdWVyeUNsaWVudC5pbnZhbGlkYXRlUXVlcmllcyh7IHF1ZXJ5S2V5OiBhbWJhc3NhZG9yS2V5cy5sZWFkZXJib2FyZCgpIH0pO1xuICAgIH0sXG4gICAgLi4ub3B0aW9ucyxcbiAgfSk7XG59XG5cbi8qKlxuICogQXBwcm92ZSBhbWJhc3NhZG9yIGFwcGxpY2F0aW9uIChhZG1pbilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZUFwcHJvdmVBbWJhc3NhZG9yKFxuICBvcHRpb25zPzogT21pdDxVc2VNdXRhdGlvbk9wdGlvbnM8QW1iYXNzYWRvclJlc3BvbnNlLCBFcnJvciwgc3RyaW5nPiwgJ211dGF0aW9uRm4nPlxuKTogVXNlTXV0YXRpb25SZXN1bHQ8QW1iYXNzYWRvclJlc3BvbnNlLCBFcnJvciwgc3RyaW5nPiB7XG4gIGNvbnN0IHF1ZXJ5Q2xpZW50ID0gdXNlUXVlcnlDbGllbnQoKTtcblxuICByZXR1cm4gdXNlTXV0YXRpb24oe1xuICAgIG11dGF0aW9uRm46IGFzeW5jIChpZDogc3RyaW5nKTogUHJvbWlzZTxBbWJhc3NhZG9yUmVzcG9uc2U+ID0+IHtcbiAgICAgIGNvbnN0IGNsaWVudCA9IGdldEFwaUNsaWVudCgpO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdChgL2FwaS92MS9hbWJhc3NhZG9ycy8ke2lkfS9hcHByb3ZlYCk7XG4gICAgICByZXR1cm4gcmVzcG9uc2UuZGF0YTtcbiAgICB9LFxuICAgIG9uU3VjY2VzczogKGFtYmFzc2Fkb3IsIGlkKSA9PiB7XG4gICAgICBxdWVyeUNsaWVudC5zZXRRdWVyeURhdGEoYW1iYXNzYWRvcktleXMuZGV0YWlsKGlkKSwgYW1iYXNzYWRvcik7XG4gICAgICBxdWVyeUNsaWVudC5pbnZhbGlkYXRlUXVlcmllcyh7IHF1ZXJ5S2V5OiBhbWJhc3NhZG9yS2V5cy5saXN0cygpIH0pO1xuICAgICAgcXVlcnlDbGllbnQuaW52YWxpZGF0ZVF1ZXJpZXMoeyBxdWVyeUtleTogYW1iYXNzYWRvcktleXMucGVuZGluZygpIH0pO1xuICAgICAgcXVlcnlDbGllbnQuaW52YWxpZGF0ZVF1ZXJpZXMoeyBxdWVyeUtleTogYW1iYXNzYWRvcktleXMubGVhZGVyYm9hcmQoKSB9KTtcbiAgICB9LFxuICAgIC4uLm9wdGlvbnMsXG4gIH0pO1xufVxuXG4vKipcbiAqIFJlamVjdCBhbWJhc3NhZG9yIGFwcGxpY2F0aW9uIChhZG1pbilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVJlamVjdEFtYmFzc2Fkb3IoXG4gIG9wdGlvbnM/OiBPbWl0PFVzZU11dGF0aW9uT3B0aW9uczx7IHN1Y2Nlc3M6IGJvb2xlYW4gfSwgRXJyb3IsIHN0cmluZz4sICdtdXRhdGlvbkZuJz5cbik6IFVzZU11dGF0aW9uUmVzdWx0PHsgc3VjY2VzczogYm9vbGVhbiB9LCBFcnJvciwgc3RyaW5nPiB7XG4gIGNvbnN0IHF1ZXJ5Q2xpZW50ID0gdXNlUXVlcnlDbGllbnQoKTtcblxuICByZXR1cm4gdXNlTXV0YXRpb24oe1xuICAgIG11dGF0aW9uRm46IGFzeW5jIChpZDogc3RyaW5nKTogUHJvbWlzZTx7IHN1Y2Nlc3M6IGJvb2xlYW4gfT4gPT4ge1xuICAgICAgY29uc3QgY2xpZW50ID0gZ2V0QXBpQ2xpZW50KCk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5wb3N0KGAvYXBpL3YxL2FtYmFzc2Fkb3JzLyR7aWR9L3JlamVjdGApO1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE7XG4gICAgfSxcbiAgICBvblN1Y2Nlc3M6IChfLCBpZCkgPT4ge1xuICAgICAgcXVlcnlDbGllbnQucmVtb3ZlUXVlcmllcyh7IHF1ZXJ5S2V5OiBhbWJhc3NhZG9yS2V5cy5kZXRhaWwoaWQpIH0pO1xuICAgICAgcXVlcnlDbGllbnQuaW52YWxpZGF0ZVF1ZXJpZXMoeyBxdWVyeUtleTogYW1iYXNzYWRvcktleXMubGlzdHMoKSB9KTtcbiAgICAgIHF1ZXJ5Q2xpZW50LmludmFsaWRhdGVRdWVyaWVzKHsgcXVlcnlLZXk6IGFtYmFzc2Fkb3JLZXlzLnBlbmRpbmcoKSB9KTtcbiAgICB9LFxuICAgIC4uLm9wdGlvbnMsXG4gIH0pO1xufVxuXG4vKipcbiAqIERlYWN0aXZhdGUgYW1iYXNzYWRvciAoYWRtaW4pXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VEZWFjdGl2YXRlQW1iYXNzYWRvcihcbiAgb3B0aW9ucz86IE9taXQ8VXNlTXV0YXRpb25PcHRpb25zPEFtYmFzc2Fkb3JSZXNwb25zZSwgRXJyb3IsIHN0cmluZz4sICdtdXRhdGlvbkZuJz5cbik6IFVzZU11dGF0aW9uUmVzdWx0PEFtYmFzc2Fkb3JSZXNwb25zZSwgRXJyb3IsIHN0cmluZz4ge1xuICBjb25zdCBxdWVyeUNsaWVudCA9IHVzZVF1ZXJ5Q2xpZW50KCk7XG5cbiAgcmV0dXJuIHVzZU11dGF0aW9uKHtcbiAgICBtdXRhdGlvbkZuOiBhc3luYyAoaWQ6IHN0cmluZyk6IFByb21pc2U8QW1iYXNzYWRvclJlc3BvbnNlPiA9PiB7XG4gICAgICBjb25zdCBjbGllbnQgPSBnZXRBcGlDbGllbnQoKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LnBvc3QoYC9hcGkvdjEvYW1iYXNzYWRvcnMvJHtpZH0vZGVhY3RpdmF0ZWApO1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE7XG4gICAgfSxcbiAgICBvblN1Y2Nlc3M6IChhbWJhc3NhZG9yLCBpZCkgPT4ge1xuICAgICAgcXVlcnlDbGllbnQuc2V0UXVlcnlEYXRhKGFtYmFzc2Fkb3JLZXlzLmRldGFpbChpZCksIGFtYmFzc2Fkb3IpO1xuICAgICAgcXVlcnlDbGllbnQuaW52YWxpZGF0ZVF1ZXJpZXMoeyBxdWVyeUtleTogYW1iYXNzYWRvcktleXMubGlzdHMoKSB9KTtcbiAgICAgIHF1ZXJ5Q2xpZW50LmludmFsaWRhdGVRdWVyaWVzKHsgcXVlcnlLZXk6IGFtYmFzc2Fkb3JLZXlzLmxlYWRlcmJvYXJkKCkgfSk7XG4gICAgfSxcbiAgICAuLi5vcHRpb25zLFxuICB9KTtcbn1cblxuLyoqXG4gKiBBZGQgcmV3YXJkIHBvaW50cyB0byBhbWJhc3NhZG9yIChhZG1pbilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZUFkZEFtYmFzc2Fkb3JSZXdhcmQoXG4gIG9wdGlvbnM/OiBPbWl0PFxuICAgIFVzZU11dGF0aW9uT3B0aW9uczx7IHN1Y2Nlc3M6IGJvb2xlYW4gfSwgRXJyb3IsIHsgaWQ6IHN0cmluZzsgcG9pbnRzOiBudW1iZXI7IHJlYXNvbj86IHN0cmluZyB9PixcbiAgICAnbXV0YXRpb25GbidcbiAgPlxuKTogVXNlTXV0YXRpb25SZXN1bHQ8eyBzdWNjZXNzOiBib29sZWFuIH0sIEVycm9yLCB7IGlkOiBzdHJpbmc7IHBvaW50czogbnVtYmVyOyByZWFzb24/OiBzdHJpbmcgfT4ge1xuICBjb25zdCBxdWVyeUNsaWVudCA9IHVzZVF1ZXJ5Q2xpZW50KCk7XG5cbiAgcmV0dXJuIHVzZU11dGF0aW9uKHtcbiAgICBtdXRhdGlvbkZuOiBhc3luYyAoeyBpZCwgcG9pbnRzLCByZWFzb24gfSk6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuIH0+ID0+IHtcbiAgICAgIGNvbnN0IGNsaWVudCA9IGdldEFwaUNsaWVudCgpO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdChgL2FwaS92MS9hbWJhc3NhZG9ycy8ke2lkfS9yZXdhcmRgLCB7IHBvaW50cywgcmVhc29uIH0pO1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE7XG4gICAgfSxcbiAgICBvblN1Y2Nlc3M6IChfLCB7IGlkIH0pID0+IHtcbiAgICAgIHF1ZXJ5Q2xpZW50LmludmFsaWRhdGVRdWVyaWVzKHsgcXVlcnlLZXk6IGFtYmFzc2Fkb3JLZXlzLmRldGFpbChpZCkgfSk7XG4gICAgICBxdWVyeUNsaWVudC5pbnZhbGlkYXRlUXVlcmllcyh7IHF1ZXJ5S2V5OiBhbWJhc3NhZG9yS2V5cy5sZWFkZXJib2FyZCgpIH0pO1xuICAgIH0sXG4gICAgLi4ub3B0aW9ucyxcbiAgfSk7XG59XG4iXX0=
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Mutation Hooks
|
|
3
|
+
*
|
|
4
|
+
* TanStack Query mutation hooks for authentication-related write operations.
|
|
5
|
+
* These hooks handle user registration, login, token refresh, and Firebase authentication.
|
|
6
|
+
*
|
|
7
|
+
* @module api/mutations/auth
|
|
8
|
+
*/
|
|
9
|
+
import { UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
10
|
+
import type { RegisterRequest, LoginRequest, RefreshTokenRequest, FirebaseAuthRequest, AuthResponse, TokenResponse } from '../types';
|
|
11
|
+
/**
|
|
12
|
+
* Register a new user account
|
|
13
|
+
*
|
|
14
|
+
* @description
|
|
15
|
+
* Creates a new user account with email/phone and password.
|
|
16
|
+
* Returns authentication tokens and user information upon successful registration.
|
|
17
|
+
*
|
|
18
|
+
* @endpoint POST /auth/register
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* import { useRegister } from '@growsober/sdk';
|
|
23
|
+
*
|
|
24
|
+
* function RegisterForm() {
|
|
25
|
+
* const { mutate: register, isPending, error } = useRegister({
|
|
26
|
+
* onSuccess: (data) => {
|
|
27
|
+
* // Store tokens securely
|
|
28
|
+
* await SecureStore.setItemAsync('accessToken', data.accessToken);
|
|
29
|
+
* await SecureStore.setItemAsync('refreshToken', data.refreshToken);
|
|
30
|
+
* navigation.navigate('Onboarding');
|
|
31
|
+
* },
|
|
32
|
+
* onError: (error) => {
|
|
33
|
+
* Alert.alert('Registration failed', error.message);
|
|
34
|
+
* },
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* const handleSubmit = () => {
|
|
38
|
+
* register({
|
|
39
|
+
* email: 'user@example.com',
|
|
40
|
+
* password: 'SecurePassword123!',
|
|
41
|
+
* name: 'John Doe',
|
|
42
|
+
* });
|
|
43
|
+
* };
|
|
44
|
+
*
|
|
45
|
+
* return <Button onPress={handleSubmit} disabled={isPending} />;
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @param options - TanStack Query mutation options
|
|
50
|
+
* @returns TanStack Query mutation result
|
|
51
|
+
*/
|
|
52
|
+
export declare function useRegister(options?: Omit<UseMutationOptions<AuthResponse, Error, RegisterRequest>, 'mutationFn'>): UseMutationResult<AuthResponse, Error, RegisterRequest>;
|
|
53
|
+
/**
|
|
54
|
+
* Login with email/phone and password
|
|
55
|
+
*
|
|
56
|
+
* @description
|
|
57
|
+
* Authenticates an existing user with their credentials.
|
|
58
|
+
* Returns authentication tokens and user information upon successful login.
|
|
59
|
+
*
|
|
60
|
+
* @endpoint POST /auth/login
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* import { useLogin } from '@growsober/sdk';
|
|
65
|
+
*
|
|
66
|
+
* function LoginForm() {
|
|
67
|
+
* const { mutate: login, isPending, error } = useLogin({
|
|
68
|
+
* onSuccess: (data) => {
|
|
69
|
+
* // Store tokens securely
|
|
70
|
+
* await SecureStore.setItemAsync('accessToken', data.accessToken);
|
|
71
|
+
* await SecureStore.setItemAsync('refreshToken', data.refreshToken);
|
|
72
|
+
* navigation.navigate('Home');
|
|
73
|
+
* },
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* const handleSubmit = () => {
|
|
77
|
+
* login({
|
|
78
|
+
* email: 'user@example.com',
|
|
79
|
+
* password: 'SecurePassword123!',
|
|
80
|
+
* });
|
|
81
|
+
* };
|
|
82
|
+
*
|
|
83
|
+
* return (
|
|
84
|
+
* <form onSubmit={handleSubmit}>
|
|
85
|
+
* <input type="email" name="email" />
|
|
86
|
+
* <input type="password" name="password" />
|
|
87
|
+
* <button type="submit" disabled={isPending}>
|
|
88
|
+
* {isPending ? 'Logging in...' : 'Login'}
|
|
89
|
+
* </button>
|
|
90
|
+
* {error && <p className="error">{error.message}</p>}
|
|
91
|
+
* </form>
|
|
92
|
+
* );
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* Login with phone number:
|
|
98
|
+
* ```tsx
|
|
99
|
+
* login({
|
|
100
|
+
* phone: '+1234567890',
|
|
101
|
+
* password: 'SecurePassword123!',
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @param options - TanStack Query mutation options
|
|
106
|
+
* @returns TanStack Query mutation result
|
|
107
|
+
*/
|
|
108
|
+
export declare function useLogin(options?: Omit<UseMutationOptions<AuthResponse, Error, LoginRequest>, 'mutationFn'>): UseMutationResult<AuthResponse, Error, LoginRequest>;
|
|
109
|
+
/**
|
|
110
|
+
* Refresh access token using refresh token
|
|
111
|
+
*
|
|
112
|
+
* @description
|
|
113
|
+
* Obtains a new access token using a valid refresh token.
|
|
114
|
+
* Should be called when the access token expires.
|
|
115
|
+
*
|
|
116
|
+
* @endpoint POST /auth/refresh
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```tsx
|
|
120
|
+
* import { useRefreshAuthToken } from '@growsober/sdk';
|
|
121
|
+
*
|
|
122
|
+
* function useTokenRefresh() {
|
|
123
|
+
* const { mutateAsync: refreshToken } = useRefreshAuthToken();
|
|
124
|
+
*
|
|
125
|
+
* const handleTokenExpired = async () => {
|
|
126
|
+
* const storedRefreshToken = await SecureStore.getItemAsync('refreshToken');
|
|
127
|
+
*
|
|
128
|
+
* if (!storedRefreshToken) {
|
|
129
|
+
* navigation.navigate('Login');
|
|
130
|
+
* return;
|
|
131
|
+
* }
|
|
132
|
+
*
|
|
133
|
+
* try {
|
|
134
|
+
* const { accessToken, refreshToken: newRefreshToken } = await refreshToken({
|
|
135
|
+
* refreshToken: storedRefreshToken,
|
|
136
|
+
* });
|
|
137
|
+
*
|
|
138
|
+
* // Store new tokens
|
|
139
|
+
* await SecureStore.setItemAsync('accessToken', accessToken);
|
|
140
|
+
* await SecureStore.setItemAsync('refreshToken', newRefreshToken);
|
|
141
|
+
* } catch (error) {
|
|
142
|
+
* // Refresh token is invalid or expired
|
|
143
|
+
* navigation.navigate('Login');
|
|
144
|
+
* }
|
|
145
|
+
* };
|
|
146
|
+
*
|
|
147
|
+
* return { handleTokenExpired };
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* Integrate with SDK configuration:
|
|
153
|
+
* ```tsx
|
|
154
|
+
* import { configureSDK } from '@growsober/sdk';
|
|
155
|
+
*
|
|
156
|
+
* configureSDK({
|
|
157
|
+
* baseURL: 'https://api.growsober.app',
|
|
158
|
+
* getAccessToken: async () => {
|
|
159
|
+
* return await SecureStore.getItemAsync('accessToken');
|
|
160
|
+
* },
|
|
161
|
+
* refreshAccessToken: async () => {
|
|
162
|
+
* const refreshToken = await SecureStore.getItemAsync('refreshToken');
|
|
163
|
+
* const { accessToken, refreshToken: newRefreshToken } = await fetch('/auth/refresh', {
|
|
164
|
+
* method: 'POST',
|
|
165
|
+
* body: JSON.stringify({ refreshToken }),
|
|
166
|
+
* }).then(r => r.json());
|
|
167
|
+
*
|
|
168
|
+
* await SecureStore.setItemAsync('accessToken', accessToken);
|
|
169
|
+
* await SecureStore.setItemAsync('refreshToken', newRefreshToken);
|
|
170
|
+
*
|
|
171
|
+
* return accessToken;
|
|
172
|
+
* },
|
|
173
|
+
* onUnauthorized: () => {
|
|
174
|
+
* navigation.navigate('Login');
|
|
175
|
+
* },
|
|
176
|
+
* });
|
|
177
|
+
* ```
|
|
178
|
+
*
|
|
179
|
+
* @param options - TanStack Query mutation options
|
|
180
|
+
* @returns TanStack Query mutation result
|
|
181
|
+
*/
|
|
182
|
+
export declare function useRefreshAuthToken(options?: Omit<UseMutationOptions<TokenResponse, Error, RefreshTokenRequest>, 'mutationFn'>): UseMutationResult<TokenResponse, Error, RefreshTokenRequest>;
|
|
183
|
+
/**
|
|
184
|
+
* Authenticate with Firebase ID token
|
|
185
|
+
*
|
|
186
|
+
* @description
|
|
187
|
+
* Authenticates a user using a Firebase ID token.
|
|
188
|
+
* Creates a new user account if one doesn't exist, or logs in an existing user.
|
|
189
|
+
* Returns GrowSober authentication tokens and user information.
|
|
190
|
+
*
|
|
191
|
+
* @endpoint POST /auth/firebase
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```tsx
|
|
195
|
+
* import { useFirebaseAuth } from '@growsober/sdk';
|
|
196
|
+
* import { signInWithPhoneNumber } from 'firebase/auth';
|
|
197
|
+
*
|
|
198
|
+
* function PhoneAuthScreen() {
|
|
199
|
+
* const { mutate: firebaseAuth, isPending } = useFirebaseAuth({
|
|
200
|
+
* onSuccess: (data) => {
|
|
201
|
+
* // Store GrowSober tokens
|
|
202
|
+
* await SecureStore.setItemAsync('accessToken', data.accessToken);
|
|
203
|
+
* await SecureStore.setItemAsync('refreshToken', data.refreshToken);
|
|
204
|
+
*
|
|
205
|
+
* if (data.user.onboardingCompleted) {
|
|
206
|
+
* navigation.navigate('Home');
|
|
207
|
+
* } else {
|
|
208
|
+
* navigation.navigate('Onboarding');
|
|
209
|
+
* }
|
|
210
|
+
* },
|
|
211
|
+
* onError: (error) => {
|
|
212
|
+
* Alert.alert('Authentication failed', error.message);
|
|
213
|
+
* },
|
|
214
|
+
* });
|
|
215
|
+
*
|
|
216
|
+
* const handlePhoneAuth = async (phoneNumber: string) => {
|
|
217
|
+
* try {
|
|
218
|
+
* // Firebase authentication flow
|
|
219
|
+
* const confirmation = await signInWithPhoneNumber(auth, phoneNumber);
|
|
220
|
+
* const code = await promptUserForCode(); // Your UI to get verification code
|
|
221
|
+
* const credential = await confirmation.confirm(code);
|
|
222
|
+
*
|
|
223
|
+
* // Get Firebase ID token
|
|
224
|
+
* const idToken = await credential.user.getIdToken();
|
|
225
|
+
*
|
|
226
|
+
* // Authenticate with GrowSober backend
|
|
227
|
+
* firebaseAuth({ idToken });
|
|
228
|
+
* } catch (error) {
|
|
229
|
+
* console.error('Phone auth error:', error);
|
|
230
|
+
* }
|
|
231
|
+
* };
|
|
232
|
+
*
|
|
233
|
+
* return <PhoneInput onSubmit={handlePhoneAuth} disabled={isPending} />;
|
|
234
|
+
* }
|
|
235
|
+
* ```
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* With Google Sign-In:
|
|
239
|
+
* ```tsx
|
|
240
|
+
* import { GoogleSignin } from '@react-native-google-signin/google-signin';
|
|
241
|
+
*
|
|
242
|
+
* const handleGoogleSignIn = async () => {
|
|
243
|
+
* const { idToken } = await GoogleSignin.signIn();
|
|
244
|
+
* firebaseAuth({ idToken });
|
|
245
|
+
* };
|
|
246
|
+
* ```
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* With Apple Sign-In:
|
|
250
|
+
* ```tsx
|
|
251
|
+
* import * as AppleAuthentication from 'expo-apple-authentication';
|
|
252
|
+
*
|
|
253
|
+
* const handleAppleSignIn = async () => {
|
|
254
|
+
* const credential = await AppleAuthentication.signInAsync({
|
|
255
|
+
* requestedScopes: [
|
|
256
|
+
* AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
|
|
257
|
+
* AppleAuthentication.AppleAuthenticationScope.EMAIL,
|
|
258
|
+
* ],
|
|
259
|
+
* });
|
|
260
|
+
* firebaseAuth({ idToken: credential.identityToken });
|
|
261
|
+
* };
|
|
262
|
+
* ```
|
|
263
|
+
*
|
|
264
|
+
* @param options - TanStack Query mutation options
|
|
265
|
+
* @returns TanStack Query mutation result
|
|
266
|
+
*/
|
|
267
|
+
export declare function useFirebaseAuth(options?: Omit<UseMutationOptions<AuthResponse, Error, FirebaseAuthRequest>, 'mutationFn'>): UseMutationResult<AuthResponse, Error, FirebaseAuthRequest>;
|