shelflife-react-hooks 1.0.18 → 1.0.20

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.
Files changed (44) hide show
  1. package/dist/index.cjs.js +23 -0
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.d.cts +2 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.esm.js +23 -0
  6. package/dist/index.esm.js.map +1 -1
  7. package/package.json +36 -36
  8. package/src/context/AuthContext.tsx +161 -161
  9. package/src/context/InviteContext.tsx +74 -74
  10. package/src/context/ProductContext.tsx +131 -121
  11. package/src/context/RunningLowContext.tsx +100 -100
  12. package/src/context/ShoppingListContext.tsx +76 -76
  13. package/src/context/StorageContext.tsx +105 -105
  14. package/src/context/StorageItemContext.tsx +157 -157
  15. package/src/context/StorageMemberContext.tsx +84 -84
  16. package/src/context/UserContext.tsx +109 -109
  17. package/src/context/__tests__/contexts.test.tsx +370 -370
  18. package/src/context/api/authApi.ts +155 -155
  19. package/src/context/api/inviteApi.ts +65 -65
  20. package/src/context/api/productApi.ts +223 -201
  21. package/src/context/api/requestState.ts +24 -24
  22. package/src/context/api/runningLowApi.ts +141 -141
  23. package/src/context/api/shoppingListApi.ts +161 -159
  24. package/src/context/api/storageApi.ts +166 -166
  25. package/src/context/api/storageItemApi.ts +260 -260
  26. package/src/context/api/storageMemberApi.ts +84 -84
  27. package/src/context/api/userApi.ts +161 -161
  28. package/src/context/http.ts +22 -22
  29. package/src/index.ts +21 -21
  30. package/src/type/PaginatedResponse.ts +8 -8
  31. package/src/type/auth.ts +79 -79
  32. package/src/type/base.ts +21 -21
  33. package/src/type/item.ts +12 -12
  34. package/src/type/member.ts +6 -6
  35. package/src/type/models.ts +56 -56
  36. package/src/type/product.ts +11 -11
  37. package/src/type/requests.ts +60 -60
  38. package/src/type/runninglow.ts +13 -13
  39. package/src/type/shoppingList.ts +13 -13
  40. package/src/type/storage.ts +7 -7
  41. package/src/type/user.ts +11 -11
  42. package/tsconfig.json +46 -46
  43. package/tsup.config.ts +10 -10
  44. package/vitest.config.ts +8 -8
@@ -1,155 +1,155 @@
1
- import type {
2
- ChangePasswordErrorResponse,
3
- ChangePasswordRequest,
4
- LoginErrorResponse,
5
- LoginRequest,
6
- LoginResponse,
7
- SignupError,
8
- SignupRequest,
9
- User
10
- } from '../../type/auth.js';
11
- import type { ErrorResponse } from '../../type/base.js';
12
- import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
13
- import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
14
-
15
- type AuthApiConfig = RequestStateHandlers & {
16
- baseUrl: string;
17
- token: string | null;
18
- setToken: (token: string | null) => void;
19
- setUser: (user: User | null) => void;
20
- };
21
-
22
- export const loginRequest = async (
23
- config: AuthApiConfig,
24
- dto: LoginRequest
25
- ): Promise<void> => runWithRequestState(config, async () => {
26
- const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
27
- const response = await fetch(`${normalizedBaseUrl}/api/auth/login`, {
28
- method: 'POST',
29
- headers: {
30
- 'Content-Type': 'application/json'
31
- },
32
- body: JSON.stringify(dto)
33
- });
34
-
35
- if (!response.ok) {
36
- const error = await readJson<LoginErrorResponse>(response);
37
-
38
- if (error?.error)
39
- throw error;
40
-
41
- throw new Error('Login failed');
42
- }
43
-
44
- const payload = await readJson<LoginResponse>(response);
45
- if (!payload || !('token' in payload)) {
46
- throw new Error('Login response missing token');
47
- }
48
-
49
- config.setToken(payload.token);
50
-
51
- const meResponse = await fetch(`${normalizedBaseUrl}/api/auth/me`, {
52
- headers: buildAuthHeaders(payload.token)
53
- });
54
-
55
- if (meResponse.ok) {
56
- const mePayload = await readJson<User>(meResponse);
57
- if (mePayload) {
58
- config.setUser(mePayload);
59
- }
60
- }
61
- });
62
-
63
- export const signupRequest = async (
64
- config: AuthApiConfig,
65
- dto: SignupRequest
66
- ): Promise<User> => runWithRequestState(config, async () => {
67
- const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
68
- const response = await fetch(`${normalizedBaseUrl}/api/auth/signup`, {
69
- method: 'POST',
70
- headers: {
71
- 'Content-Type': 'application/json'
72
- },
73
- body: JSON.stringify(dto)
74
- });
75
-
76
- if (!response.ok) {
77
- const error = await readJson<SignupError>(response);
78
-
79
- if (error?.email || error?.password || error?.passwordRepeat || error?.username )
80
- throw error;
81
-
82
- throw new Error('Signup failed');
83
- }
84
-
85
- const payload = await readJson<User>(response);
86
- if (!payload) {
87
- throw new Error('Signup response missing user');
88
- }
89
-
90
- return payload;
91
- });
92
-
93
- export const changePasswordRequest = async (
94
- config: AuthApiConfig,
95
- dto: ChangePasswordRequest
96
- ): Promise<void> => runWithRequestState(config, async () => {
97
- const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
98
- const response = await fetch(`${normalizedBaseUrl}/api/auth/password/change`, {
99
- method: 'POST',
100
- headers: {
101
- ...buildAuthHeaders(config.token),
102
- 'Content-Type': 'application/json'
103
- },
104
- body: JSON.stringify(dto)
105
- });
106
-
107
- if (!response.ok) {
108
- const error = await readJson<ChangePasswordErrorResponse>(response);
109
-
110
- if (error?.oldPassword || error?.newPassword || error?.newPasswordRepeat)
111
- throw error;
112
-
113
- throw new Error('Change password failed');
114
- }
115
- });
116
-
117
- export const getMeRequest = async (config: AuthApiConfig): Promise<User | null> => runWithRequestState(
118
- config,
119
- async () => {
120
- const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
121
- const response = await fetch(`${normalizedBaseUrl}/api/auth/me`, {
122
- headers: buildAuthHeaders(config.token)
123
- });
124
-
125
- if (!response.ok) {
126
- config.setUser(null);
127
- return null;
128
- }
129
-
130
- const payload = await readJson<User>(response);
131
- if (!payload) {
132
- config.setUser(null);
133
- return null;
134
- }
135
-
136
- config.setUser(payload);
137
- return payload;
138
- }
139
- );
140
-
141
- export const logoutRequest = async (config: AuthApiConfig): Promise<void> => runWithRequestState(
142
- config,
143
- async () => {
144
- const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
145
- if (config.token) {
146
- await fetch(`${normalizedBaseUrl}/api/auth/logout`, {
147
- method: 'POST',
148
- headers: buildAuthHeaders(config.token)
149
- });
150
- }
151
-
152
- config.setToken(null);
153
- config.setUser(null);
154
- }
155
- );
1
+ import type {
2
+ ChangePasswordErrorResponse,
3
+ ChangePasswordRequest,
4
+ LoginErrorResponse,
5
+ LoginRequest,
6
+ LoginResponse,
7
+ SignupError,
8
+ SignupRequest,
9
+ User
10
+ } from '../../type/auth.js';
11
+ import type { ErrorResponse } from '../../type/base.js';
12
+ import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
13
+ import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
14
+
15
+ type AuthApiConfig = RequestStateHandlers & {
16
+ baseUrl: string;
17
+ token: string | null;
18
+ setToken: (token: string | null) => void;
19
+ setUser: (user: User | null) => void;
20
+ };
21
+
22
+ export const loginRequest = async (
23
+ config: AuthApiConfig,
24
+ dto: LoginRequest
25
+ ): Promise<void> => runWithRequestState(config, async () => {
26
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
27
+ const response = await fetch(`${normalizedBaseUrl}/api/auth/login`, {
28
+ method: 'POST',
29
+ headers: {
30
+ 'Content-Type': 'application/json'
31
+ },
32
+ body: JSON.stringify(dto)
33
+ });
34
+
35
+ if (!response.ok) {
36
+ const error = await readJson<LoginErrorResponse>(response);
37
+
38
+ if (error?.error)
39
+ throw error;
40
+
41
+ throw new Error('Login failed');
42
+ }
43
+
44
+ const payload = await readJson<LoginResponse>(response);
45
+ if (!payload || !('token' in payload)) {
46
+ throw new Error('Login response missing token');
47
+ }
48
+
49
+ config.setToken(payload.token);
50
+
51
+ const meResponse = await fetch(`${normalizedBaseUrl}/api/auth/me`, {
52
+ headers: buildAuthHeaders(payload.token)
53
+ });
54
+
55
+ if (meResponse.ok) {
56
+ const mePayload = await readJson<User>(meResponse);
57
+ if (mePayload) {
58
+ config.setUser(mePayload);
59
+ }
60
+ }
61
+ });
62
+
63
+ export const signupRequest = async (
64
+ config: AuthApiConfig,
65
+ dto: SignupRequest
66
+ ): Promise<User> => runWithRequestState(config, async () => {
67
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
68
+ const response = await fetch(`${normalizedBaseUrl}/api/auth/signup`, {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json'
72
+ },
73
+ body: JSON.stringify(dto)
74
+ });
75
+
76
+ if (!response.ok) {
77
+ const error = await readJson<SignupError>(response);
78
+
79
+ if (error?.email || error?.password || error?.passwordRepeat || error?.username )
80
+ throw error;
81
+
82
+ throw new Error('Signup failed');
83
+ }
84
+
85
+ const payload = await readJson<User>(response);
86
+ if (!payload) {
87
+ throw new Error('Signup response missing user');
88
+ }
89
+
90
+ return payload;
91
+ });
92
+
93
+ export const changePasswordRequest = async (
94
+ config: AuthApiConfig,
95
+ dto: ChangePasswordRequest
96
+ ): Promise<void> => runWithRequestState(config, async () => {
97
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
98
+ const response = await fetch(`${normalizedBaseUrl}/api/auth/password/change`, {
99
+ method: 'POST',
100
+ headers: {
101
+ ...buildAuthHeaders(config.token),
102
+ 'Content-Type': 'application/json'
103
+ },
104
+ body: JSON.stringify(dto)
105
+ });
106
+
107
+ if (!response.ok) {
108
+ const error = await readJson<ChangePasswordErrorResponse>(response);
109
+
110
+ if (error?.oldPassword || error?.newPassword || error?.newPasswordRepeat)
111
+ throw error;
112
+
113
+ throw new Error('Change password failed');
114
+ }
115
+ });
116
+
117
+ export const getMeRequest = async (config: AuthApiConfig): Promise<User | null> => runWithRequestState(
118
+ config,
119
+ async () => {
120
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
121
+ const response = await fetch(`${normalizedBaseUrl}/api/auth/me`, {
122
+ headers: buildAuthHeaders(config.token)
123
+ });
124
+
125
+ if (!response.ok) {
126
+ config.setUser(null);
127
+ return null;
128
+ }
129
+
130
+ const payload = await readJson<User>(response);
131
+ if (!payload) {
132
+ config.setUser(null);
133
+ return null;
134
+ }
135
+
136
+ config.setUser(payload);
137
+ return payload;
138
+ }
139
+ );
140
+
141
+ export const logoutRequest = async (config: AuthApiConfig): Promise<void> => runWithRequestState(
142
+ config,
143
+ async () => {
144
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
145
+ if (config.token) {
146
+ await fetch(`${normalizedBaseUrl}/api/auth/logout`, {
147
+ method: 'POST',
148
+ headers: buildAuthHeaders(config.token)
149
+ });
150
+ }
151
+
152
+ config.setToken(null);
153
+ config.setUser(null);
154
+ }
155
+ );
@@ -1,65 +1,65 @@
1
- import type { StorageMember } from '../../type/models.js';
2
- import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
3
- import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
4
-
5
- type InviteApiConfig = RequestStateHandlers & {
6
- baseUrl: string;
7
- token: string | null;
8
- setInvites: (value: StorageMember[] | ((items: StorageMember[]) => StorageMember[])) => void;
9
- };
10
-
11
- export const fetchInvitesRequest = async (config: InviteApiConfig): Promise<StorageMember[]> => runWithRequestState(
12
- config,
13
- async () => {
14
- const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
15
- const response = await fetch(`${normalizedBaseUrl}/api/storages/invites`, {
16
- headers: buildAuthHeaders(config.token)
17
- });
18
-
19
- if (!response.ok) {
20
- throw new Error('Failed to fetch invites');
21
- }
22
-
23
- const payload = await readJson<StorageMember[]>(response);
24
- if (payload) {
25
- config.setInvites(payload);
26
- return payload;
27
- }
28
-
29
- return [];
30
- }
31
- );
32
-
33
- export const acceptInviteRequest = async (
34
- config: InviteApiConfig,
35
- id: number
36
- ): Promise<void> => runWithRequestState(config, async () => {
37
- const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
38
- const response = await fetch(`${normalizedBaseUrl}/api/storages/invites/${id}`, {
39
- method: 'POST',
40
- headers: buildAuthHeaders(config.token)
41
- });
42
-
43
- if (!response.ok) {
44
- throw new Error('Failed to accept invite');
45
- }
46
-
47
- config.setInvites((previous) => previous.filter((invite) => invite.id !== id));
48
- });
49
-
50
- export const declineInviteRequest = async (
51
- config: InviteApiConfig,
52
- id: number
53
- ): Promise<void> => runWithRequestState(config, async () => {
54
- const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
55
- const response = await fetch(`${normalizedBaseUrl}/api/storages/invites/${id}`, {
56
- method: 'DELETE',
57
- headers: buildAuthHeaders(config.token)
58
- });
59
-
60
- if (!response.ok) {
61
- throw new Error('Failed to decline invite');
62
- }
63
-
64
- config.setInvites((previous) => previous.filter((invite) => invite.id !== id));
65
- });
1
+ import type { StorageMember } from '../../type/models.js';
2
+ import { buildAuthHeaders, normalizeBaseUrl, readJson } from '../http.js';
3
+ import { runWithRequestState, type RequestStateHandlers } from './requestState.js';
4
+
5
+ type InviteApiConfig = RequestStateHandlers & {
6
+ baseUrl: string;
7
+ token: string | null;
8
+ setInvites: (value: StorageMember[] | ((items: StorageMember[]) => StorageMember[])) => void;
9
+ };
10
+
11
+ export const fetchInvitesRequest = async (config: InviteApiConfig): Promise<StorageMember[]> => runWithRequestState(
12
+ config,
13
+ async () => {
14
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
15
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/invites`, {
16
+ headers: buildAuthHeaders(config.token)
17
+ });
18
+
19
+ if (!response.ok) {
20
+ throw new Error('Failed to fetch invites');
21
+ }
22
+
23
+ const payload = await readJson<StorageMember[]>(response);
24
+ if (payload) {
25
+ config.setInvites(payload);
26
+ return payload;
27
+ }
28
+
29
+ return [];
30
+ }
31
+ );
32
+
33
+ export const acceptInviteRequest = async (
34
+ config: InviteApiConfig,
35
+ id: number
36
+ ): Promise<void> => runWithRequestState(config, async () => {
37
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
38
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/invites/${id}`, {
39
+ method: 'POST',
40
+ headers: buildAuthHeaders(config.token)
41
+ });
42
+
43
+ if (!response.ok) {
44
+ throw new Error('Failed to accept invite');
45
+ }
46
+
47
+ config.setInvites((previous) => previous.filter((invite) => invite.id !== id));
48
+ });
49
+
50
+ export const declineInviteRequest = async (
51
+ config: InviteApiConfig,
52
+ id: number
53
+ ): Promise<void> => runWithRequestState(config, async () => {
54
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
55
+ const response = await fetch(`${normalizedBaseUrl}/api/storages/invites/${id}`, {
56
+ method: 'DELETE',
57
+ headers: buildAuthHeaders(config.token)
58
+ });
59
+
60
+ if (!response.ok) {
61
+ throw new Error('Failed to decline invite');
62
+ }
63
+
64
+ config.setInvites((previous) => previous.filter((invite) => invite.id !== id));
65
+ });