fetchwire 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/dist/index.mjs ADDED
@@ -0,0 +1,246 @@
1
+ // src/util/api-error.ts
2
+ var ApiError = class extends Error {
3
+ constructor(message, errorCode, statusCode) {
4
+ super(message);
5
+ this.name = "ApiError";
6
+ this.errorCode = errorCode;
7
+ this.statusCode = statusCode;
8
+ }
9
+ };
10
+
11
+ // src/core/config.ts
12
+ var globalWireConfig = null;
13
+ var initWire = (config) => {
14
+ globalWireConfig = {
15
+ ...config,
16
+ headers: config.headers || {}
17
+ };
18
+ };
19
+ var updateWireConfig = (config) => {
20
+ if (!globalWireConfig) {
21
+ throw new Error("Wire not initialized. Call initWire() first.");
22
+ }
23
+ globalWireConfig = {
24
+ ...globalWireConfig,
25
+ ...config,
26
+ headers: {
27
+ ...globalWireConfig.headers,
28
+ ...config.headers
29
+ }
30
+ };
31
+ };
32
+ var getWireConfig = () => {
33
+ if (!globalWireConfig) {
34
+ throw new Error("Wire not initialized. Call initWire() first.");
35
+ }
36
+ return globalWireConfig;
37
+ };
38
+
39
+ // src/core/wire.ts
40
+ async function wireApi(endpoint, options = {}) {
41
+ const config = getWireConfig();
42
+ const url = `${config.baseUrl}${endpoint}`;
43
+ const accessToken = await config.getToken();
44
+ const headers = {
45
+ "Content-Type": "application/json",
46
+ ...accessToken ? { Authorization: `Bearer ${accessToken}` } : {},
47
+ ...config.headers,
48
+ ...options.headers
49
+ };
50
+ try {
51
+ const response = await fetch(url, { ...options, headers });
52
+ if (!response.ok) {
53
+ let errorData;
54
+ try {
55
+ errorData = await response.json();
56
+ } catch {
57
+ errorData = { message: "Unknown server error", error: "UNKNOWN" };
58
+ }
59
+ const apiError = new ApiError(
60
+ errorData.message,
61
+ errorData.error,
62
+ response.status
63
+ );
64
+ const unauthorizedStatusCodes = config.unauthorizedStatusCodes && config.unauthorizedStatusCodes.length > 0 ? config.unauthorizedStatusCodes : [401];
65
+ const forbiddenStatusCodes = config.forbiddenStatusCodes && config.forbiddenStatusCodes.length > 0 ? config.forbiddenStatusCodes : [403];
66
+ if (config.interceptors?.onUnauthorized && unauthorizedStatusCodes.includes(response.status)) {
67
+ config.interceptors.onUnauthorized(apiError);
68
+ } else if (config.interceptors?.onForbidden && forbiddenStatusCodes.includes(response.status)) {
69
+ config.interceptors.onForbidden(apiError);
70
+ } else if (config.interceptors?.onError) {
71
+ config.interceptors.onError(apiError);
72
+ }
73
+ throw apiError;
74
+ }
75
+ return await response.json();
76
+ } catch (error) {
77
+ if (error instanceof ApiError) throw error;
78
+ throw new ApiError(
79
+ error instanceof Error ? error.message : "Network error",
80
+ "NETWORK_ERROR",
81
+ 520
82
+ );
83
+ }
84
+ }
85
+
86
+ // src/hook/use-fetch-fn.ts
87
+ import { useState, useRef, useEffect, useCallback } from "react";
88
+
89
+ // src/core/event-emitter.ts
90
+ var EventEmitter = class {
91
+ constructor() {
92
+ this.events = {};
93
+ }
94
+ emit(event) {
95
+ if (!this.events[event]) return;
96
+ this.events[event].forEach((listener) => listener());
97
+ }
98
+ addListener(event, listener) {
99
+ if (!this.events[event]) {
100
+ this.events[event] = [];
101
+ }
102
+ this.events[event].push(listener);
103
+ return {
104
+ remove: () => {
105
+ this.events[event] = this.events[event].filter((l) => l !== listener);
106
+ }
107
+ };
108
+ }
109
+ };
110
+ var eventEmitter = new EventEmitter();
111
+
112
+ // src/hook/use-fetch-fn.ts
113
+ function useFetchFn(options) {
114
+ const [state, setState] = useState({
115
+ data: null,
116
+ isLoading: false,
117
+ isRefreshing: false,
118
+ error: null
119
+ });
120
+ const isMounted = useRef(true);
121
+ const lastFetchFn = useRef(null);
122
+ useEffect(() => {
123
+ isMounted.current = true;
124
+ return () => {
125
+ isMounted.current = false;
126
+ };
127
+ }, []);
128
+ const execute = useCallback(
129
+ async (fetchFn, execOptions) => {
130
+ lastFetchFn.current = fetchFn;
131
+ setState((prev) => ({
132
+ ...prev,
133
+ isLoading: !execOptions.isRefresh,
134
+ isRefreshing: !!execOptions.isRefresh,
135
+ error: null
136
+ }));
137
+ try {
138
+ const response = await fetchFn();
139
+ if (isMounted.current) {
140
+ setState({
141
+ data: response.data || null,
142
+ isLoading: false,
143
+ isRefreshing: false,
144
+ error: null
145
+ });
146
+ }
147
+ return response;
148
+ } catch (error) {
149
+ const apiError = error;
150
+ if (isMounted.current) {
151
+ setState({
152
+ data: null,
153
+ isLoading: false,
154
+ isRefreshing: false,
155
+ error: apiError
156
+ });
157
+ }
158
+ return null;
159
+ }
160
+ },
161
+ []
162
+ );
163
+ const executeFetchFn = useCallback(
164
+ (fetchFn) => {
165
+ return execute(fetchFn, { isRefresh: false });
166
+ },
167
+ [execute]
168
+ );
169
+ const refreshFetchFn = useCallback(() => {
170
+ if (lastFetchFn.current) {
171
+ return execute(lastFetchFn.current, { isRefresh: true });
172
+ }
173
+ return null;
174
+ }, [execute]);
175
+ useEffect(() => {
176
+ if (!options?.tags || options.tags.length === 0) return;
177
+ const subscriptions = options.tags.map(
178
+ (tag) => eventEmitter.addListener(tag, () => {
179
+ refreshFetchFn();
180
+ })
181
+ );
182
+ return () => subscriptions.forEach((sub) => sub.remove());
183
+ }, [options?.tags, refreshFetchFn]);
184
+ return { ...state, executeFetchFn, refreshFetchFn };
185
+ }
186
+
187
+ // src/hook/use-mutation-fn.ts
188
+ import { useState as useState2, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect2 } from "react";
189
+ function useMutationFn(options) {
190
+ const [state, setState] = useState2({
191
+ data: null,
192
+ isMutating: false
193
+ });
194
+ const isMounted = useRef2(true);
195
+ useEffect2(() => {
196
+ isMounted.current = true;
197
+ return () => {
198
+ isMounted.current = false;
199
+ };
200
+ }, []);
201
+ const executeMutationFn = useCallback2(
202
+ async (mutationFn, executeOptions) => {
203
+ setState((prev) => ({ ...prev, isMutating: true }));
204
+ try {
205
+ const response = await mutationFn();
206
+ if (isMounted.current) {
207
+ setState({
208
+ data: response.data || null,
209
+ isMutating: false
210
+ });
211
+ options?.invalidatesTags?.forEach((tag) => {
212
+ eventEmitter.emit(tag);
213
+ });
214
+ if (response.data) executeOptions?.onSuccess?.(response.data);
215
+ else executeOptions?.onSuccess?.(null);
216
+ }
217
+ return response;
218
+ } catch (error) {
219
+ const apiError = error;
220
+ if (isMounted.current) {
221
+ setState({
222
+ data: null,
223
+ isMutating: false
224
+ });
225
+ if (apiError) executeOptions?.onError?.(apiError);
226
+ }
227
+ return null;
228
+ }
229
+ },
230
+ [options?.invalidatesTags]
231
+ );
232
+ const reset = useCallback2(() => {
233
+ setState({ data: null, isMutating: false });
234
+ }, []);
235
+ return { ...state, executeMutationFn, reset };
236
+ }
237
+ export {
238
+ ApiError,
239
+ getWireConfig,
240
+ initWire,
241
+ updateWireConfig,
242
+ useFetchFn,
243
+ useMutationFn,
244
+ wireApi
245
+ };
246
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/util/api-error.ts","../src/core/config.ts","../src/core/wire.ts","../src/hook/use-fetch-fn.ts","../src/core/event-emitter.ts","../src/hook/use-mutation-fn.ts"],"sourcesContent":["export class ApiError extends Error {\n public errorCode?: string;\n public statusCode?: number;\n\n constructor(message: string, errorCode?: string, statusCode?: number) {\n super(message);\n this.name = 'ApiError';\n this.errorCode = errorCode;\n this.statusCode = statusCode;\n }\n}","import { WireConfig } from '../interface';\n\nlet globalWireConfig: WireConfig | null = null;\n\n/**\n * Initializes the library with mandatory configurations.\n * Must be executed at the application entry point before any API calls.\n * @param config - The required configuration object including baseUrl and getToken.\n */\nexport const initWire = (config: WireConfig): void => {\n globalWireConfig = {\n ...config,\n headers: config.headers || {},\n };\n};\n\n/**\n * Updates the existing configuration.\n * Merges new headers with existing ones and overrides other provided fields.\n * @param config - A partial configuration object to update.\n */\nexport const updateWireConfig = (config: Partial<WireConfig>): void => {\n if (!globalWireConfig) {\n throw new Error('Wire not initialized. Call initWire() first.');\n }\n\n globalWireConfig = {\n ...globalWireConfig,\n ...config,\n headers: {\n ...globalWireConfig.headers,\n ...config.headers,\n },\n };\n};\n\n/**\n * Retrieves the current global configuration state.\n * @throws Error if the configuration state is null.\n * @returns The validated WireConfig object.\n */\nexport const getWireConfig = (): WireConfig => {\n if (!globalWireConfig) {\n throw new Error('Wire not initialized. Call initWire() first.');\n }\n return globalWireConfig;\n};","import { HttpResponse } from '../interface';\nimport { ApiError } from '../util/api-error';\nimport { getWireConfig } from './config';\n\n/**\n * Sends an API request and returns the response.\n * @param endpoint - The API endpoint to call. Example: '/api/v1/users'.\n * @param options - The request options is a RequestInit object.\n */\nexport async function wireApi<T>(\n endpoint: string,\n options: RequestInit = {}\n): Promise<HttpResponse<T>> {\n const config = getWireConfig();\n const url = `${config.baseUrl}${endpoint}`;\n const accessToken = await config.getToken();\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),\n ...config.headers,\n ...options.headers,\n };\n\n try {\n const response = await fetch(url, { ...options, headers });\n\n if (!response.ok) {\n let errorData;\n try {\n errorData = await response.json();\n } catch {\n errorData = { message: 'Unknown server error', error: 'UNKNOWN' };\n }\n\n const apiError = new ApiError(\n errorData.message,\n errorData.error,\n response.status\n );\n\n // Resolve effective status-code mappings with default values\n const unauthorizedStatusCodes =\n config.unauthorizedStatusCodes && config.unauthorizedStatusCodes.length > 0\n ? config.unauthorizedStatusCodes\n : [401];\n\n const forbiddenStatusCodes =\n config.forbiddenStatusCodes && config.forbiddenStatusCodes.length > 0\n ? config.forbiddenStatusCodes\n : [403];\n\n // Trigger interceptors based on configured status codes\n if (\n config.interceptors?.onUnauthorized &&\n unauthorizedStatusCodes.includes(response.status)\n ) {\n config.interceptors.onUnauthorized(apiError);\n } else if (\n config.interceptors?.onForbidden &&\n forbiddenStatusCodes.includes(response.status)\n ) {\n config.interceptors.onForbidden(apiError);\n } else if (config.interceptors?.onError) {\n config.interceptors.onError(apiError);\n }\n\n throw apiError;\n }\n\n return await response.json();\n } catch (error) {\n if (error instanceof ApiError) throw error;\n throw new ApiError(\n error instanceof Error ? error.message : 'Network error',\n 'NETWORK_ERROR',\n 520\n );\n }\n}\n","import { useState, useRef, useEffect, useCallback } from 'react';\nimport { ApiError } from '../util/api-error';\nimport { HttpResponse, FetchOptions } from '../interface';\nimport { eventEmitter } from '../core/event-emitter';\n\ninterface FetchState<T> {\n data: T | null;\n isLoading: boolean;\n isRefreshing: boolean;\n error: ApiError | null;\n}\n\n/**\n * A hook for executing a fetch function and managing the state of the fetch.\n * @param options - Has tags property that will trigger refetching of the useFetchFn with the given tags.\n * @returns The state of the fetch and the fetch function.\n */\nexport function useFetchFn<T>(options?: FetchOptions) {\n const [state, setState] = useState<FetchState<T>>({\n data: null,\n isLoading: false,\n isRefreshing: false,\n error: null,\n });\n\n const isMounted = useRef<boolean>(true);\n const lastFetchFn = useRef<(() => Promise<HttpResponse<T>>) | null>(null);\n\n useEffect(() => {\n isMounted.current = true;\n return () => {\n isMounted.current = false;\n };\n }, []);\n\n const execute = useCallback(\n async (\n fetchFn: () => Promise<HttpResponse<T>>,\n execOptions: { isRefresh: boolean }\n ): Promise<HttpResponse<T> | null> => {\n lastFetchFn.current = fetchFn;\n\n setState((prev) => ({\n ...prev,\n isLoading: !execOptions.isRefresh,\n isRefreshing: !!execOptions.isRefresh,\n error: null,\n }));\n\n try {\n const response = await fetchFn();\n\n if (isMounted.current) {\n setState({\n data: response.data || null,\n isLoading: false,\n isRefreshing: false,\n error: null,\n });\n }\n return response;\n } catch (error) {\n const apiError = error as ApiError;\n if (isMounted.current) {\n setState({\n data: null,\n isLoading: false,\n isRefreshing: false,\n error: apiError,\n });\n }\n return null;\n }\n },\n []\n );\n\n const executeFetchFn = useCallback(\n (fetchFn: () => Promise<HttpResponse<T>>) => {\n return execute(fetchFn, { isRefresh: false });\n },\n [execute]\n );\n\n const refreshFetchFn = useCallback(() => {\n if (lastFetchFn.current) {\n return execute(lastFetchFn.current, { isRefresh: true });\n }\n return null;\n }, [execute]);\n\n useEffect(() => {\n if (!options?.tags || options.tags.length === 0) return;\n\n const subscriptions = options.tags.map((tag) =>\n eventEmitter.addListener(tag, () => {\n refreshFetchFn();\n })\n );\n return () => subscriptions.forEach((sub) => sub.remove());\n }, [options?.tags, refreshFetchFn]);\n\n return { ...state, executeFetchFn, refreshFetchFn };\n}\n","type Listener = () => void;\n\nclass EventEmitter {\n private events: Record<string, Listener[]> = {};\n\n emit(event: string) {\n if (!this.events[event]) return;\n this.events[event].forEach((listener) => listener());\n }\n\n addListener(event: string, listener: Listener) {\n if (!this.events[event]) {\n this.events[event] = [];\n }\n this.events[event].push(listener);\n \n return {\n remove: () => {\n this.events[event] = this.events[event].filter((l) => l !== listener);\n },\n };\n }\n}\n\nexport const eventEmitter = new EventEmitter();","import { useState, useCallback, useRef, useEffect } from 'react';\nimport { ApiError } from '../util/api-error';\nimport { HttpResponse, MutationOptions, ExecuteMutationOptions } from '../interface';\nimport { eventEmitter } from '../core/event-emitter';\n\ninterface MutationState<T> {\n data: T | null;\n isMutating: boolean;\n}\n\n/**\n * A hook for executing a mutation function and managing the state of the mutation.\n * @param options - Has invalidatesTags property that will trigger refetching of the useFetchFn with the given tags.\n * @returns The state of the mutation and the mutation function.\n */\nexport function useMutationFn<T>(options?: MutationOptions) {\n const [state, setState] = useState<MutationState<T>>({\n data: null,\n isMutating: false,\n });\n const isMounted = useRef<boolean>(true);\n \n useEffect(() => {\n isMounted.current = true;\n return () => {\n isMounted.current = false;\n };\n }, []);\n\n const executeMutationFn = useCallback(\n async (\n mutationFn: () => Promise<HttpResponse<T>>,\n executeOptions?: ExecuteMutationOptions<T>\n ): Promise<HttpResponse<T> | null> => {\n setState((prev) => ({ ...prev, isMutating: true }));\n\n try {\n const response = await mutationFn();\n \n if (isMounted.current) {\n setState({\n data: response.data || null,\n isMutating: false,\n });\n \n options?.invalidatesTags?.forEach((tag) => {\n eventEmitter.emit(tag);\n });\n \n if (response.data) executeOptions?.onSuccess?.(response.data);\n else executeOptions?.onSuccess?.(null as unknown as T);\n }\n return response;\n } catch (error) {\n const apiError = error as ApiError;\n if (isMounted.current) {\n setState({\n data: null,\n isMutating: false,\n });\n if (apiError) executeOptions?.onError?.(apiError);\n }\n return null;\n }\n },\n [options?.invalidatesTags]\n );\n\n const reset = useCallback(() => {\n setState({ data: null, isMutating: false });\n }, []);\n\n return { ...state, executeMutationFn, reset };\n}"],"mappings":"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","names":["useState","useCallback","useRef","useEffect","useState","useRef","useEffect","useCallback"]}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "fetchwire",
3
+ "version": "1.0.0",
4
+ "description": "A lightweight, focused API fetching library for React and React Native applications.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsup",
10
+ "dev": "tsup --watch"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "keywords": [
16
+ "fetch",
17
+ "fetchwire",
18
+ "hooks"
19
+ ],
20
+ "author": "Doanvinhphu",
21
+ "license": "MIT",
22
+ "devDependencies": {
23
+ "@types/react": "^19.2.14",
24
+ "tsup": "^8.5.1",
25
+ "typescript": "^5.9.3"
26
+ },
27
+ "funding": [
28
+ {
29
+ "type": "ko-fi",
30
+ "url": "https://ko-fi.com/doanvinhphu"
31
+ },
32
+ {
33
+ "type": "custom",
34
+ "url": "https://paypal.me/doanvinhphu"
35
+ }
36
+ ]
37
+ }