katanakit-js 6.2.0 → 6.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -3
- package/dist/adapters/better-auth/better-auth.service.d.ts +83 -0
- package/dist/adapters/better-auth/better-auth.service.d.ts.map +1 -0
- package/dist/adapters/better-auth/better-auth.service.js +110 -0
- package/dist/adapters/better-auth/better-auth.service.js.map +1 -0
- package/dist/adapters/better-auth/client.d.ts +51 -0
- package/dist/adapters/better-auth/client.d.ts.map +1 -0
- package/dist/adapters/better-auth/client.js +67 -0
- package/dist/adapters/better-auth/client.js.map +1 -0
- package/dist/adapters/better-auth/index.d.ts +3 -0
- package/dist/adapters/better-auth/index.d.ts.map +1 -0
- package/dist/adapters/better-auth/index.js +3 -0
- package/dist/adapters/better-auth/index.js.map +1 -0
- package/dist/adapters/express/server.d.ts +133 -1
- package/dist/adapters/express/server.d.ts.map +1 -1
- package/dist/adapters/express/server.js +199 -97
- package/dist/adapters/express/server.js.map +1 -1
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +2 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/insforge/insforge.service.d.ts +139 -4
- package/dist/adapters/insforge/insforge.service.d.ts.map +1 -1
- package/dist/adapters/insforge/insforge.service.js +383 -213
- package/dist/adapters/insforge/insforge.service.js.map +1 -1
- package/dist/adapters/notion/notion.service.d.ts +130 -144
- package/dist/adapters/notion/notion.service.d.ts.map +1 -1
- package/dist/adapters/notion/notion.service.js +330 -341
- package/dist/adapters/notion/notion.service.js.map +1 -1
- package/dist/adapters/photoswipe/index.d.ts +2 -0
- package/dist/adapters/photoswipe/index.d.ts.map +1 -0
- package/dist/adapters/photoswipe/index.js +2 -0
- package/dist/adapters/photoswipe/index.js.map +1 -0
- package/dist/adapters/photoswipe/photoswipe.service.d.ts +99 -0
- package/dist/adapters/photoswipe/photoswipe.service.d.ts.map +1 -0
- package/dist/adapters/photoswipe/photoswipe.service.js +150 -0
- package/dist/adapters/photoswipe/photoswipe.service.js.map +1 -0
- package/dist/adapters/telegram/telegram.service.d.ts +82 -13
- package/dist/adapters/telegram/telegram.service.d.ts.map +1 -1
- package/dist/adapters/telegram/telegram.service.js +133 -55
- package/dist/adapters/telegram/telegram.service.js.map +1 -1
- package/dist/adapters/wordpress/wordpress.service.d.ts +181 -110
- package/dist/adapters/wordpress/wordpress.service.d.ts.map +1 -1
- package/dist/adapters/wordpress/wordpress.service.js +556 -465
- package/dist/adapters/wordpress/wordpress.service.js.map +1 -1
- package/dist/config/seo.service.d.ts +1 -1
- package/dist/config/seo.service.d.ts.map +1 -1
- package/dist/config/seo.service.js +1 -1
- package/dist/config/seo.service.js.map +1 -1
- package/dist/core/services/access.service.d.ts +167 -4
- package/dist/core/services/access.service.d.ts.map +1 -1
- package/dist/core/services/access.service.js +241 -31
- package/dist/core/services/access.service.js.map +1 -1
- package/dist/core/services/agent.service.d.ts +182 -27
- package/dist/core/services/agent.service.d.ts.map +1 -1
- package/dist/core/services/agent.service.js +296 -164
- package/dist/core/services/agent.service.js.map +1 -1
- package/dist/core/services/assistant.service.d.ts +96 -5
- package/dist/core/services/assistant.service.d.ts.map +1 -1
- package/dist/core/services/assistant.service.js +171 -66
- package/dist/core/services/assistant.service.js.map +1 -1
- package/dist/core/services/dates.service.d.ts +183 -11
- package/dist/core/services/dates.service.d.ts.map +1 -1
- package/dist/core/services/dates.service.js +256 -57
- package/dist/core/services/dates.service.js.map +1 -1
- package/dist/core/services/http.service.d.ts +172 -133
- package/dist/core/services/http.service.d.ts.map +1 -1
- package/dist/core/services/http.service.js +367 -310
- package/dist/core/services/http.service.js.map +1 -1
- package/dist/core/services/logger.service.d.ts +96 -34
- package/dist/core/services/logger.service.d.ts.map +1 -1
- package/dist/core/services/logger.service.js +128 -41
- package/dist/core/services/logger.service.js.map +1 -1
- package/dist/core/services/query.service.d.ts +101 -0
- package/dist/core/services/query.service.d.ts.map +1 -1
- package/dist/core/services/query.service.js +131 -14
- package/dist/core/services/query.service.js.map +1 -1
- package/dist/core/services/utils.service.d.ts +286 -131
- package/dist/core/services/utils.service.d.ts.map +1 -1
- package/dist/core/services/utils.service.js +417 -227
- package/dist/core/services/utils.service.js.map +1 -1
- package/dist/core/services/validation.service.d.ts +48 -3
- package/dist/core/services/validation.service.d.ts.map +1 -1
- package/dist/core/services/validation.service.js +75 -23
- package/dist/core/services/validation.service.js.map +1 -1
- package/dist/infrastructure/decorators/cache.decorator.d.ts +53 -0
- package/dist/infrastructure/decorators/cache.decorator.d.ts.map +1 -0
- package/dist/infrastructure/decorators/cache.decorator.js +47 -0
- package/dist/infrastructure/decorators/cache.decorator.js.map +1 -0
- package/dist/infrastructure/decorators/index.d.ts +4 -0
- package/dist/infrastructure/decorators/index.d.ts.map +1 -0
- package/dist/infrastructure/decorators/index.js +4 -0
- package/dist/infrastructure/decorators/index.js.map +1 -0
- package/dist/infrastructure/decorators/logger.decorator.d.ts +38 -0
- package/dist/infrastructure/decorators/logger.decorator.d.ts.map +1 -0
- package/dist/infrastructure/decorators/logger.decorator.js +66 -0
- package/dist/infrastructure/decorators/logger.decorator.js.map +1 -0
- package/dist/infrastructure/decorators/retry.decorator.d.ts +37 -0
- package/dist/infrastructure/decorators/retry.decorator.d.ts.map +1 -0
- package/dist/infrastructure/decorators/retry.decorator.js +54 -0
- package/dist/infrastructure/decorators/retry.decorator.js.map +1 -0
- package/dist/infrastructure/index.d.ts +1 -0
- package/dist/infrastructure/index.d.ts.map +1 -1
- package/dist/infrastructure/index.js +1 -0
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/styles.css +2 -0
- package/package.json +49 -14
- package/scss/_flags.scss +179 -0
- package/scss/_functions.scss +168 -0
- package/scss/_mixins.scss +658 -0
- package/scss/_reset.scss +275 -0
- package/scss/_utilities.scss +449 -0
- package/scss/_variables.scss +539 -0
- package/scss/components/_index.scss +50 -0
- package/scss/demo.scss +12 -0
- package/scss/main.scss +56 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useTryJsonParse } from "./result.service.js";
|
|
2
2
|
import { useSplitConfig } from "./utils.service.js";
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/** Error bodies are truncated so a hostile response cannot exhaust memory. */
|
|
4
|
+
const MAX_ERROR_BODY_CHARS = 32 * 1024;
|
|
5
5
|
/**
|
|
6
6
|
* Internal: narrows an unknown literal entry to an {@link ApiEntry}.
|
|
7
7
|
*
|
|
@@ -11,28 +11,12 @@ let apis = {};
|
|
|
11
11
|
function isApiEntry(value) {
|
|
12
12
|
return typeof value === "object" && value !== null && "baseUri" in value && "endpoints" in value;
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
15
|
-
* Internal: retrieves a registered API entry or throws.
|
|
16
|
-
*
|
|
17
|
-
* @param apiName - The key of the API in the registry.
|
|
18
|
-
* @returns The {@link ApiEntry} for the given name.
|
|
19
|
-
* @throws {Error} If the API is not registered.
|
|
20
|
-
*/
|
|
21
|
-
function getApiEntry(apiName) {
|
|
22
|
-
const api = apis[apiName];
|
|
23
|
-
if (!api) {
|
|
24
|
-
throw new Error(`[FetchApiManager] API "${apiName}" is not registered.`);
|
|
25
|
-
}
|
|
26
|
-
return api;
|
|
27
|
-
}
|
|
28
14
|
/**
|
|
29
15
|
* Internal: reads a Response body, attempting JSON parse for JSON content types.
|
|
30
16
|
*
|
|
31
17
|
* @param response - The fetch Response to read.
|
|
32
18
|
* @returns The parsed body or `null` for empty responses.
|
|
33
19
|
*/
|
|
34
|
-
/** Error bodies are truncated so a hostile response cannot exhaust memory. */
|
|
35
|
-
const MAX_ERROR_BODY_CHARS = 32 * 1024;
|
|
36
20
|
async function readBody(response, maxChars) {
|
|
37
21
|
const text = await response.text();
|
|
38
22
|
if (!text)
|
|
@@ -72,7 +56,338 @@ function serializeBody(body) {
|
|
|
72
56
|
};
|
|
73
57
|
}
|
|
74
58
|
/**
|
|
75
|
-
*
|
|
59
|
+
* Picks the URL-building keys out of an options bag so nothing else leaks into
|
|
60
|
+
* the `RequestInit` handed to `fetch`.
|
|
61
|
+
*
|
|
62
|
+
* @param urlOptions - Legacy URL options, if any.
|
|
63
|
+
* @returns Only `params`, `query` and `ignoreDefaultQuery`, when defined.
|
|
64
|
+
*/
|
|
65
|
+
function pickUrl(urlOptions) {
|
|
66
|
+
if (!urlOptions)
|
|
67
|
+
return {};
|
|
68
|
+
const { params, query, ignoreDefaultQuery } = urlOptions;
|
|
69
|
+
return {
|
|
70
|
+
...(params !== undefined && { params }),
|
|
71
|
+
...(query !== undefined && { query }),
|
|
72
|
+
...(ignoreDefaultQuery !== undefined && { ignoreDefaultQuery }),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* FetchApiManager - Singleton para el registro de APIs y peticiones HTTP.
|
|
77
|
+
*
|
|
78
|
+
* Aplica el patrón Singleton: una única instancia mantiene el registro de APIs
|
|
79
|
+
* (`ApisConfig`) y centraliza la construcción de URLs y las peticiones fetch,
|
|
80
|
+
* devolviendo siempre Safe Results (nunca lanza en rutas async).
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* const fetchApi = FetchApiManager.getInstance();
|
|
85
|
+
* fetchApi.useInit({ pokeapi: { baseUri: "https://pokeapi.co/api/v2", endpoints: { byId: "/pokemon/:id/" } } });
|
|
86
|
+
* const result = await fetchApi.useFetch("pokeapi", "byId", { params: { id: 25 } });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export class FetchApiManager {
|
|
90
|
+
static instance;
|
|
91
|
+
/** Module-level API registry. */
|
|
92
|
+
apis = {};
|
|
93
|
+
/**
|
|
94
|
+
* Constructor privado - enforce singleton.
|
|
95
|
+
*/
|
|
96
|
+
constructor() { }
|
|
97
|
+
/**
|
|
98
|
+
* Obtiene la instancia única del FetchApiManager (Singleton).
|
|
99
|
+
*
|
|
100
|
+
* @returns La instancia única de {@link FetchApiManager}.
|
|
101
|
+
*/
|
|
102
|
+
static getInstance() {
|
|
103
|
+
if (!FetchApiManager.instance) {
|
|
104
|
+
FetchApiManager.instance = new FetchApiManager();
|
|
105
|
+
}
|
|
106
|
+
return FetchApiManager.instance;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Internal: retrieves a registered API entry or throws.
|
|
110
|
+
*
|
|
111
|
+
* @param apiName - The key of the API in the registry.
|
|
112
|
+
* @returns The {@link ApiEntry} for the given name.
|
|
113
|
+
* @throws {Error} If the API is not registered.
|
|
114
|
+
*/
|
|
115
|
+
useGetApiEntry(apiName) {
|
|
116
|
+
const api = this.apis[apiName];
|
|
117
|
+
if (!api) {
|
|
118
|
+
throw new Error(`[FetchApiManager] API "${apiName}" is not registered.`);
|
|
119
|
+
}
|
|
120
|
+
return api;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Registers (merges) API definitions into the client registry.
|
|
124
|
+
*
|
|
125
|
+
* @param apisConfig - The API definitions to merge into the registry.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* FetchApiManager.getInstance().useInit({
|
|
130
|
+
* pokeapi: { baseUri: "https://pokeapi.co/api/v2", endpoints: { pokemonById: "/pokemon/:id/" } },
|
|
131
|
+
* });
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
useInit(apisConfig) {
|
|
135
|
+
this.apis = { ...this.apis, ...apisConfig };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Returns a shallow copy of the registered APIs (safe to mutate locally).
|
|
139
|
+
*
|
|
140
|
+
* @returns A shallow copy of the current API registry.
|
|
141
|
+
*/
|
|
142
|
+
useGetApis() {
|
|
143
|
+
return { ...this.apis };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Returns the URL of a registered endpoint **without calling `fetch`**.
|
|
147
|
+
*
|
|
148
|
+
* It builds the same URL {@link useFetch} would request - same registry,
|
|
149
|
+
* same `:param` substitution, same `query` merge with `defaultQueryParams`,
|
|
150
|
+
* same http(s) guard - then stops and hands you the string.
|
|
151
|
+
*
|
|
152
|
+
* @param apiName - Registered API key (from `defineApiConfig`).
|
|
153
|
+
* @param endpointName - Endpoint key inside that API.
|
|
154
|
+
* @param options - `params` fills `:placeholders`, `query` becomes the search string.
|
|
155
|
+
* @returns The fully built URL.
|
|
156
|
+
* @throws {Error} Unknown API, unknown endpoint, or a scheme that is not http(s).
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* FetchApiManager.getInstance().useBuildUrl("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
161
|
+
* // → "https://pokeapi.co/api/v2/pokemon/25"
|
|
162
|
+
* ```
|
|
163
|
+
*
|
|
164
|
+
* @remarks Synchronous, so it **throws** instead of returning a Safe Result -
|
|
165
|
+
* Safe Result covers fallible async work, and this never leaves the process.
|
|
166
|
+
*/
|
|
167
|
+
useBuildUrl(apiName, endpointName, options = {}) {
|
|
168
|
+
const { params, query, ignoreDefaultQuery = false } = options;
|
|
169
|
+
const api = this.useGetApiEntry(apiName);
|
|
170
|
+
let path = api.endpoints?.[endpointName] ?? "";
|
|
171
|
+
if (!path) {
|
|
172
|
+
throw new Error(`[FetchApiManager] Endpoint "${endpointName}" not found in API "${apiName}".`);
|
|
173
|
+
}
|
|
174
|
+
if (params) {
|
|
175
|
+
const escapeRegex = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
176
|
+
path = Object.entries(params).reduce((acc, [key, value]) => acc.replace(new RegExp(`:${escapeRegex(key)}\\b`, "g"), encodeURIComponent(String(value))), path);
|
|
177
|
+
}
|
|
178
|
+
const baseStr = api.baseUri instanceof URL ? api.baseUri.toString() : api.baseUri;
|
|
179
|
+
const baseClean = baseStr.endsWith("/") ? baseStr.slice(0, -1) : baseStr;
|
|
180
|
+
const pathClean = path.startsWith("/") ? path : `/${path}`;
|
|
181
|
+
const url = new URL(`${baseClean}${pathClean}`);
|
|
182
|
+
// Only allow http(s) to prevent SSRF and `javascript:` URLs.
|
|
183
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
184
|
+
throw new Error(`[FetchApiManager] Scheme "${url.protocol}" is not allowed.`);
|
|
185
|
+
}
|
|
186
|
+
const defaultParams = ignoreDefaultQuery ? {} : (api.defaultQueryParams?.[endpointName] ?? {});
|
|
187
|
+
const mergedQuery = { ...defaultParams, ...query };
|
|
188
|
+
for (const [key, value] of Object.entries(mergedQuery)) {
|
|
189
|
+
if (value !== undefined && value !== null) {
|
|
190
|
+
url.searchParams.set(key, String(value));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return url.toString();
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Fetches a registered endpoint and returns a Safe Result.
|
|
197
|
+
*
|
|
198
|
+
* URL options sit at the top level, next to `method`/`headers`/`body` - no
|
|
199
|
+
* nesting, same shape as `useGet` and Nuxt's `useFetch`.
|
|
200
|
+
*
|
|
201
|
+
* @param apiName - The registered API key.
|
|
202
|
+
* @param endpointName - The endpoint key within the API.
|
|
203
|
+
* @param options - Fetch options: `params`, `query`, `transform` and any `RequestInit` field.
|
|
204
|
+
* @returns A `FetchResult` with data or error. Never throws - a failing
|
|
205
|
+
* `transform` comes back as an error result too.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```ts
|
|
209
|
+
* const result = await FetchApiManager.getInstance().useFetch<{ results: unknown[] }>(
|
|
210
|
+
* "pokeapi",
|
|
211
|
+
* "pokemons",
|
|
212
|
+
* { method: "GET", query: { limit: 2 } },
|
|
213
|
+
* );
|
|
214
|
+
* if (result.ok) console.log(result.data.results);
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
async useFetch(apiName, endpointName, { params, query, ignoreDefaultQuery, urlOptions, transform, ...init } = {}) {
|
|
218
|
+
let url = "";
|
|
219
|
+
// The flat keys and the deprecated `urlOptions` nest describe the same
|
|
220
|
+
// thing; the flat form wins. `undefined` means "not given", so it must not
|
|
221
|
+
// overwrite a value coming from the legacy nest.
|
|
222
|
+
const buildOptions = { ...urlOptions };
|
|
223
|
+
if (params !== undefined)
|
|
224
|
+
buildOptions.params = params;
|
|
225
|
+
if (query !== undefined)
|
|
226
|
+
buildOptions.query = query;
|
|
227
|
+
if (ignoreDefaultQuery !== undefined)
|
|
228
|
+
buildOptions.ignoreDefaultQuery = ignoreDefaultQuery;
|
|
229
|
+
try {
|
|
230
|
+
url = this.useBuildUrl(apiName, endpointName, buildOptions);
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
234
|
+
return {
|
|
235
|
+
data: null,
|
|
236
|
+
error: {
|
|
237
|
+
message: `Config Error: ${message}`,
|
|
238
|
+
status: 0,
|
|
239
|
+
},
|
|
240
|
+
url,
|
|
241
|
+
status: 0,
|
|
242
|
+
ok: false,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
// Fail closed on redirects: the scheme allow-list only validates the
|
|
247
|
+
// initial URL, so following a 3xx could steer the request to a private
|
|
248
|
+
// host (SSRF). Callers that need redirects can pass `redirect: "follow"`.
|
|
249
|
+
const response = await fetch(url, { redirect: "error", ...init });
|
|
250
|
+
if (!response.ok) {
|
|
251
|
+
const errorDetails = await readBody(response, MAX_ERROR_BODY_CHARS);
|
|
252
|
+
return {
|
|
253
|
+
data: null,
|
|
254
|
+
error: {
|
|
255
|
+
message: `HTTP Error: ${response.statusText || "Unsuccessful response"}`,
|
|
256
|
+
status: response.status,
|
|
257
|
+
details: errorDetails,
|
|
258
|
+
},
|
|
259
|
+
url: response.url || url,
|
|
260
|
+
status: response.status,
|
|
261
|
+
ok: false,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
// 204 No Content and empty bodies are valid success responses.
|
|
265
|
+
const body = response.status === 204 ? null : await readBody(response);
|
|
266
|
+
let data = body;
|
|
267
|
+
if (transform) {
|
|
268
|
+
try {
|
|
269
|
+
data = await transform(body);
|
|
270
|
+
}
|
|
271
|
+
catch (err) {
|
|
272
|
+
// A failing transform is still a failed request - return it as a
|
|
273
|
+
// Safe Result instead of letting it escape `useFetch`.
|
|
274
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
275
|
+
return {
|
|
276
|
+
data: null,
|
|
277
|
+
error: {
|
|
278
|
+
message: `Transform Error: ${message}`,
|
|
279
|
+
status: response.status,
|
|
280
|
+
},
|
|
281
|
+
url: response.url || url,
|
|
282
|
+
status: response.status,
|
|
283
|
+
ok: false,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
data: data,
|
|
289
|
+
error: null,
|
|
290
|
+
url: response.url || url,
|
|
291
|
+
status: response.status,
|
|
292
|
+
ok: true,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
297
|
+
return {
|
|
298
|
+
data: null,
|
|
299
|
+
error: {
|
|
300
|
+
message: `Network/Client Error: ${message}`,
|
|
301
|
+
status: 0,
|
|
302
|
+
},
|
|
303
|
+
url,
|
|
304
|
+
status: 0,
|
|
305
|
+
ok: false,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* GET helper over a registered API endpoint.
|
|
311
|
+
*
|
|
312
|
+
* @param apiName - The registered API key.
|
|
313
|
+
* @param endpointName - The endpoint key within the API.
|
|
314
|
+
* @param urlOptions - Optional URL building options.
|
|
315
|
+
* @returns A `FetchResult` with data or error.
|
|
316
|
+
*/
|
|
317
|
+
async useGet(apiName, endpointName, urlOptions) {
|
|
318
|
+
return this.useFetch(apiName, endpointName, {
|
|
319
|
+
method: "GET",
|
|
320
|
+
...pickUrl(urlOptions),
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* POST helper over a registered API endpoint.
|
|
325
|
+
*
|
|
326
|
+
* @param apiName - The registered API key.
|
|
327
|
+
* @param endpointName - The endpoint key within the API.
|
|
328
|
+
* @param body - Optional request body (auto-serialized to JSON unless raw).
|
|
329
|
+
* @param urlOptions - Optional URL building options.
|
|
330
|
+
* @returns A `FetchResult` with data or error.
|
|
331
|
+
*/
|
|
332
|
+
async usePost(apiName, endpointName, body, urlOptions) {
|
|
333
|
+
return this.useFetch(apiName, endpointName, {
|
|
334
|
+
method: "POST",
|
|
335
|
+
...serializeBody(body),
|
|
336
|
+
...pickUrl(urlOptions),
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* PUT helper over a registered API endpoint.
|
|
341
|
+
*
|
|
342
|
+
* @param apiName - The registered API key.
|
|
343
|
+
* @param endpointName - The endpoint key within the API.
|
|
344
|
+
* @param body - Optional request body (auto-serialized to JSON unless raw).
|
|
345
|
+
* @param urlOptions - Optional URL building options.
|
|
346
|
+
* @returns A `FetchResult` with data or error.
|
|
347
|
+
*/
|
|
348
|
+
async usePut(apiName, endpointName, body, urlOptions) {
|
|
349
|
+
return this.useFetch(apiName, endpointName, {
|
|
350
|
+
method: "PUT",
|
|
351
|
+
...serializeBody(body),
|
|
352
|
+
...pickUrl(urlOptions),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* PATCH helper over a registered API endpoint.
|
|
357
|
+
*
|
|
358
|
+
* @param apiName - The registered API key.
|
|
359
|
+
* @param endpointName - The endpoint key within the API.
|
|
360
|
+
* @param body - Optional request body (auto-serialized to JSON unless raw).
|
|
361
|
+
* @param urlOptions - Optional URL building options.
|
|
362
|
+
* @returns A `FetchResult` with data or error.
|
|
363
|
+
*/
|
|
364
|
+
async usePatch(apiName, endpointName, body, urlOptions) {
|
|
365
|
+
return this.useFetch(apiName, endpointName, {
|
|
366
|
+
method: "PATCH",
|
|
367
|
+
...serializeBody(body),
|
|
368
|
+
...pickUrl(urlOptions),
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* DELETE helper over a registered API endpoint.
|
|
373
|
+
*
|
|
374
|
+
* @param apiName - The registered API key.
|
|
375
|
+
* @param endpointName - The endpoint key within the API.
|
|
376
|
+
* @param urlOptions - Optional URL building options.
|
|
377
|
+
* @returns A `FetchResult` with data or error.
|
|
378
|
+
*/
|
|
379
|
+
async useDelete(apiName, endpointName, urlOptions) {
|
|
380
|
+
return this.useFetch(apiName, endpointName, {
|
|
381
|
+
method: "DELETE",
|
|
382
|
+
...pickUrl(urlOptions),
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/* -------------------------------------------------------------------------- */
|
|
387
|
+
/* define*Config */
|
|
388
|
+
/* -------------------------------------------------------------------------- */
|
|
389
|
+
/**
|
|
390
|
+
* Declares the API registry in a single call - the config-file entry point.
|
|
76
391
|
*
|
|
77
392
|
* Registers every {@link ApiEntry} you list and returns them alongside the
|
|
78
393
|
* props, flags and methods declared on the same literal, so one `export default`
|
|
@@ -83,7 +398,7 @@ function serializeBody(body) {
|
|
|
83
398
|
*
|
|
84
399
|
* @typeParam T - The literal passed in.
|
|
85
400
|
* @param input - API entries, flags and methods in one object literal.
|
|
86
|
-
* @returns The registered config plus the declared methods (see
|
|
401
|
+
* @returns The registered config plus the declared methods (see `ConfigFacade`).
|
|
87
402
|
* @throws {Error} If a non-method value is an object that is not an API entry.
|
|
88
403
|
*
|
|
89
404
|
* @example
|
|
@@ -99,7 +414,7 @@ function serializeBody(body) {
|
|
|
99
414
|
* });
|
|
100
415
|
* ```
|
|
101
416
|
*
|
|
102
|
-
* @remarks Methods must be written with `function`, not as arrows
|
|
417
|
+
* @remarks Methods must be written with `function`, not as arrows - `this.config`
|
|
103
418
|
* is undefined inside an arrow function.
|
|
104
419
|
*/
|
|
105
420
|
export function defineApiConfig(input) {
|
|
@@ -119,6 +434,9 @@ export function defineApiConfig(input) {
|
|
|
119
434
|
// `methods` is a generic spread, so TS cannot prove the exact facade shape.
|
|
120
435
|
return { config, ...methods };
|
|
121
436
|
}
|
|
437
|
+
/* -------------------------------------------------------------------------- */
|
|
438
|
+
/* Wrappers (backward compatibility) */
|
|
439
|
+
/* -------------------------------------------------------------------------- */
|
|
122
440
|
/**
|
|
123
441
|
* Registers (merges) API definitions into the client registry.
|
|
124
442
|
*
|
|
@@ -131,36 +449,18 @@ export function defineApiConfig(input) {
|
|
|
131
449
|
* ```ts
|
|
132
450
|
* import { useInit } from "katanakit-js";
|
|
133
451
|
*
|
|
134
|
-
* useInit({
|
|
135
|
-
* pokeapi: {
|
|
136
|
-
* baseUri: "https://pokeapi.co/api/v2",
|
|
137
|
-
* endpoints: { pokemonById: "/pokemon/:id/" },
|
|
138
|
-
* },
|
|
139
|
-
* });
|
|
452
|
+
* useInit({ pokeapi: { baseUri: "https://pokeapi.co/api/v2", endpoints: { pokemonById: "/pokemon/:id/" } } });
|
|
140
453
|
* ```
|
|
141
454
|
*/
|
|
142
455
|
export function useInit(apisConfig) {
|
|
143
|
-
|
|
456
|
+
FetchApiManager.getInstance().useInit(apisConfig);
|
|
144
457
|
}
|
|
145
458
|
/**
|
|
146
459
|
* Registers (merges) API definitions into the client registry.
|
|
147
460
|
*
|
|
148
|
-
* @deprecated Use {@link defineApiConfig}
|
|
149
|
-
* returns it with any methods declared on the same literal.
|
|
461
|
+
* @deprecated Use {@link defineApiConfig}.
|
|
150
462
|
*
|
|
151
463
|
* @param apisConfig - The API definitions to merge into the registry.
|
|
152
|
-
*
|
|
153
|
-
* @example
|
|
154
|
-
* ```ts
|
|
155
|
-
* import { useInitApis } from "katanakit-js";
|
|
156
|
-
*
|
|
157
|
-
* useInitApis({
|
|
158
|
-
* pokeapi: {
|
|
159
|
-
* baseUri: "https://pokeapi.co/api/v2",
|
|
160
|
-
* endpoints: { pokemonById: "/pokemon/:id/" },
|
|
161
|
-
* },
|
|
162
|
-
* });
|
|
163
|
-
* ```
|
|
164
464
|
*/
|
|
165
465
|
export function useInitApis(apisConfig) {
|
|
166
466
|
useInit(apisConfig);
|
|
@@ -178,20 +478,12 @@ export function useInitApis(apisConfig) {
|
|
|
178
478
|
* ```
|
|
179
479
|
*/
|
|
180
480
|
export function useGetApis() {
|
|
181
|
-
return
|
|
481
|
+
return FetchApiManager.getInstance().useGetApis();
|
|
182
482
|
}
|
|
183
483
|
/**
|
|
184
|
-
* Returns a shallow copy of the registered APIs.
|
|
185
|
-
* Alias for {@link useGetApis}.
|
|
484
|
+
* Returns a shallow copy of the registered APIs. Alias for {@link useGetApis}.
|
|
186
485
|
*
|
|
187
486
|
* @returns A shallow copy of the current API registry.
|
|
188
|
-
*
|
|
189
|
-
* @example
|
|
190
|
-
* ```ts
|
|
191
|
-
* import { useGetApisConfig } from "katanakit-js";
|
|
192
|
-
*
|
|
193
|
-
* const apis = useGetApisConfig();
|
|
194
|
-
* ```
|
|
195
487
|
*/
|
|
196
488
|
export function useGetApisConfig() {
|
|
197
489
|
return useGetApis();
|
|
@@ -199,18 +491,7 @@ export function useGetApisConfig() {
|
|
|
199
491
|
/**
|
|
200
492
|
* Returns the URL of a registered endpoint **without calling `fetch`**.
|
|
201
493
|
*
|
|
202
|
-
*
|
|
203
|
-
* `:param` substitution, same `query` merge with `defaultQueryParams`, same
|
|
204
|
-
* http(s) guard — then stops and hands you the string.
|
|
205
|
-
*
|
|
206
|
-
* Use it when you need the **address**, not the response:
|
|
207
|
-
*
|
|
208
|
-
* - `<a href>` / `<img src>` — links and media built from an endpoint name
|
|
209
|
-
* - libraries that fetch on their own (charts, maps, analytics)
|
|
210
|
-
* - logging the exact URL you are about to request
|
|
211
|
-
* - SSR / prerender, where nothing should be requested
|
|
212
|
-
*
|
|
213
|
-
* @param apiName - Registered API key (from {@link defineApiConfig}).
|
|
494
|
+
* @param apiName - Registered API key (from `defineApiConfig`).
|
|
214
495
|
* @param endpointName - Endpoint key inside that API.
|
|
215
496
|
* @param options - `params` fills `:placeholders`, `query` becomes the search string.
|
|
216
497
|
* @returns The fully built URL.
|
|
@@ -222,208 +503,43 @@ export function useGetApisConfig() {
|
|
|
222
503
|
*
|
|
223
504
|
* useBuildUrl("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
224
505
|
* // → "https://pokeapi.co/api/v2/pokemon/25"
|
|
225
|
-
*
|
|
226
|
-
* useBuildUrl("myApi", "export", { query: { format: "pdf" } });
|
|
227
|
-
* // → "https://api.myapp.com/v1/export?format=pdf"
|
|
228
|
-
*
|
|
229
|
-
* <a href={useBuildUrl("myApi", "download", { params: { id: 42 } })}>Download</a>
|
|
230
506
|
* ```
|
|
231
|
-
*
|
|
232
|
-
* @remarks Synchronous, so it **throws** instead of returning a Safe Result —
|
|
233
|
-
* Safe Result covers fallible async work, and this never leaves the process.
|
|
234
|
-
* To see the URL a request actually used, read `result.url` off a `useFetch`
|
|
235
|
-
* result instead.
|
|
236
507
|
*/
|
|
237
508
|
export function useBuildUrl(apiName, endpointName, options = {}) {
|
|
238
|
-
|
|
239
|
-
const api = getApiEntry(apiName);
|
|
240
|
-
let path = api.endpoints?.[endpointName] ?? "";
|
|
241
|
-
if (!path) {
|
|
242
|
-
throw new Error(`[FetchApiManager] Endpoint "${endpointName}" not found in API "${apiName}".`);
|
|
243
|
-
}
|
|
244
|
-
if (params) {
|
|
245
|
-
const escapeRegex = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
246
|
-
path = Object.entries(params).reduce((acc, [key, value]) => acc.replace(new RegExp(`:${escapeRegex(key)}\\b`, "g"), encodeURIComponent(String(value))), path);
|
|
247
|
-
}
|
|
248
|
-
const baseStr = api.baseUri instanceof URL ? api.baseUri.toString() : api.baseUri;
|
|
249
|
-
const baseClean = baseStr.endsWith("/") ? baseStr.slice(0, -1) : baseStr;
|
|
250
|
-
const pathClean = path.startsWith("/") ? path : `/${path}`;
|
|
251
|
-
const url = new URL(`${baseClean}${pathClean}`);
|
|
252
|
-
// Only allow http(s) to prevent SSRF and `javascript:` URLs.
|
|
253
|
-
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
254
|
-
throw new Error(`[FetchApiManager] Scheme "${url.protocol}" is not allowed.`);
|
|
255
|
-
}
|
|
256
|
-
const defaultParams = ignoreDefaultQuery ? {} : (api.defaultQueryParams?.[endpointName] ?? {});
|
|
257
|
-
const mergedQuery = { ...defaultParams, ...query };
|
|
258
|
-
for (const [key, value] of Object.entries(mergedQuery)) {
|
|
259
|
-
if (value !== undefined && value !== null) {
|
|
260
|
-
url.searchParams.set(key, String(value));
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return url.toString();
|
|
509
|
+
return FetchApiManager.getInstance().useBuildUrl(apiName, endpointName, options);
|
|
264
510
|
}
|
|
265
511
|
/**
|
|
266
512
|
* Builds a safe http(s) URL from a registered API + endpoint.
|
|
267
513
|
*
|
|
268
|
-
* @deprecated Use {@link useBuildUrl}.
|
|
269
|
-
*
|
|
514
|
+
* @deprecated Use {@link useBuildUrl}. Behaviourally identical wrapper kept
|
|
515
|
+
* for backwards compatibility - scheduled for removal in the next major.
|
|
270
516
|
*
|
|
271
517
|
* @param apiName - The registered API key.
|
|
272
518
|
* @param endpointName - The endpoint key within the API.
|
|
273
519
|
* @param options - Optional URL building options.
|
|
274
520
|
* @returns The fully constructed URL string.
|
|
275
|
-
*
|
|
276
|
-
* @example
|
|
277
|
-
* ```ts
|
|
278
|
-
* import { useBuildApiUrl } from "katanakit-js";
|
|
279
|
-
*
|
|
280
|
-
* const url = useBuildApiUrl("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
281
|
-
* ```
|
|
282
521
|
*/
|
|
283
522
|
export function useBuildApiUrl(apiName, endpointName, options = {}) {
|
|
284
523
|
return useBuildUrl(apiName, endpointName, options);
|
|
285
524
|
}
|
|
286
|
-
/**
|
|
287
|
-
* Picks the URL-building keys out of an options bag so nothing else leaks into
|
|
288
|
-
* the `RequestInit` handed to `fetch`.
|
|
289
|
-
*
|
|
290
|
-
* `useGet`/`usePost`/… accept `UrlOptions`, but JS callers can stuff arbitrary
|
|
291
|
-
* keys in there; spreading the whole bag would let a stray `method`, `headers`
|
|
292
|
-
* or `body` silently override what the wrapper already set.
|
|
293
|
-
*
|
|
294
|
-
* @param urlOptions - Legacy URL options, if any.
|
|
295
|
-
* @returns Only `params`, `query` and `ignoreDefaultQuery`, when defined.
|
|
296
|
-
*/
|
|
297
|
-
function pickUrl(urlOptions) {
|
|
298
|
-
if (!urlOptions)
|
|
299
|
-
return {};
|
|
300
|
-
const { params, query, ignoreDefaultQuery } = urlOptions;
|
|
301
|
-
return {
|
|
302
|
-
...(params !== undefined && { params }),
|
|
303
|
-
...(query !== undefined && { query }),
|
|
304
|
-
...(ignoreDefaultQuery !== undefined && { ignoreDefaultQuery }),
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
525
|
/**
|
|
308
526
|
* Fetches a registered endpoint and returns a Safe Result.
|
|
309
527
|
*
|
|
310
|
-
* URL options sit at the top level, next to `method`/`headers`/`body` — no
|
|
311
|
-
* nesting, same shape as `useGet` and Nuxt's `useFetch`.
|
|
312
|
-
*
|
|
313
528
|
* @param apiName - The registered API key.
|
|
314
529
|
* @param endpointName - The endpoint key within the API.
|
|
315
530
|
* @param options - Fetch options: `params`, `query`, `transform` and any `RequestInit` field.
|
|
316
|
-
* @returns A
|
|
317
|
-
* `transform` comes back as an error result too.
|
|
531
|
+
* @returns A `FetchResult` with data or error. Never throws.
|
|
318
532
|
*
|
|
319
533
|
* @example
|
|
320
534
|
* ```ts
|
|
321
535
|
* import { useFetch } from "katanakit-js";
|
|
322
536
|
*
|
|
323
|
-
* const result = await useFetch
|
|
324
|
-
*
|
|
325
|
-
* query: { limit: 2 },
|
|
326
|
-
* transform: (body) => ({ results: (body as { results: unknown[] }).results }),
|
|
327
|
-
* });
|
|
328
|
-
* if (result.ok) console.log(result.data.results);
|
|
329
|
-
* ```
|
|
330
|
-
*
|
|
331
|
-
* @example Legacy nested form (deprecated)
|
|
332
|
-
* ```ts
|
|
333
|
-
* useFetch("pokeapi", "pokemonById", { urlOptions: { params: { id: 25 } } });
|
|
537
|
+
* const result = await useFetch("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
538
|
+
* if (result.ok) console.log(result.data);
|
|
334
539
|
* ```
|
|
335
540
|
*/
|
|
336
|
-
export async function useFetch(apiName, endpointName,
|
|
337
|
-
|
|
338
|
-
// The flat keys and the deprecated `urlOptions` nest describe the same
|
|
339
|
-
// thing; the flat form wins. `undefined` means "not given", so it must not
|
|
340
|
-
// overwrite a value coming from the legacy nest.
|
|
341
|
-
const buildOptions = { ...urlOptions };
|
|
342
|
-
if (params !== undefined)
|
|
343
|
-
buildOptions.params = params;
|
|
344
|
-
if (query !== undefined)
|
|
345
|
-
buildOptions.query = query;
|
|
346
|
-
if (ignoreDefaultQuery !== undefined)
|
|
347
|
-
buildOptions.ignoreDefaultQuery = ignoreDefaultQuery;
|
|
348
|
-
try {
|
|
349
|
-
url = useBuildUrl(apiName, endpointName, buildOptions);
|
|
350
|
-
}
|
|
351
|
-
catch (err) {
|
|
352
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
353
|
-
return {
|
|
354
|
-
data: null,
|
|
355
|
-
error: {
|
|
356
|
-
message: `Config Error: ${message}`,
|
|
357
|
-
status: 0,
|
|
358
|
-
},
|
|
359
|
-
url,
|
|
360
|
-
status: 0,
|
|
361
|
-
ok: false,
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
try {
|
|
365
|
-
// Fail closed on redirects: the scheme allow-list only validates the
|
|
366
|
-
// initial URL, so following a 3xx could steer the request to a private
|
|
367
|
-
// host (SSRF). Callers that need redirects can pass `redirect: "follow"`.
|
|
368
|
-
const response = await fetch(url, { redirect: "error", ...init });
|
|
369
|
-
if (!response.ok) {
|
|
370
|
-
const errorDetails = await readBody(response, MAX_ERROR_BODY_CHARS);
|
|
371
|
-
return {
|
|
372
|
-
data: null,
|
|
373
|
-
error: {
|
|
374
|
-
message: `HTTP Error: ${response.statusText || "Unsuccessful response"}`,
|
|
375
|
-
status: response.status,
|
|
376
|
-
details: errorDetails,
|
|
377
|
-
},
|
|
378
|
-
url: response.url || url,
|
|
379
|
-
status: response.status,
|
|
380
|
-
ok: false,
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
// 204 No Content and empty bodies are valid success responses.
|
|
384
|
-
const body = response.status === 204 ? null : await readBody(response);
|
|
385
|
-
let data = body;
|
|
386
|
-
if (transform) {
|
|
387
|
-
try {
|
|
388
|
-
data = await transform(body);
|
|
389
|
-
}
|
|
390
|
-
catch (err) {
|
|
391
|
-
// A failing transform is still a failed request — return it as a
|
|
392
|
-
// Safe Result instead of letting it escape `useFetch`.
|
|
393
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
394
|
-
return {
|
|
395
|
-
data: null,
|
|
396
|
-
error: {
|
|
397
|
-
message: `Transform Error: ${message}`,
|
|
398
|
-
status: response.status,
|
|
399
|
-
},
|
|
400
|
-
url: response.url || url,
|
|
401
|
-
status: response.status,
|
|
402
|
-
ok: false,
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
return {
|
|
407
|
-
data: data,
|
|
408
|
-
error: null,
|
|
409
|
-
url: response.url || url,
|
|
410
|
-
status: response.status,
|
|
411
|
-
ok: true,
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
catch (err) {
|
|
415
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
416
|
-
return {
|
|
417
|
-
data: null,
|
|
418
|
-
error: {
|
|
419
|
-
message: `Network/Client Error: ${message}`,
|
|
420
|
-
status: 0,
|
|
421
|
-
},
|
|
422
|
-
url,
|
|
423
|
-
status: 0,
|
|
424
|
-
ok: false,
|
|
425
|
-
};
|
|
426
|
-
}
|
|
541
|
+
export async function useFetch(apiName, endpointName, options = {}) {
|
|
542
|
+
return FetchApiManager.getInstance().useFetch(apiName, endpointName, options);
|
|
427
543
|
}
|
|
428
544
|
/**
|
|
429
545
|
* Fetches a registered endpoint and returns a Safe Result.
|
|
@@ -432,18 +548,7 @@ export async function useFetch(apiName, endpointName, { params, query, ignoreDef
|
|
|
432
548
|
* @param apiName - The registered API key.
|
|
433
549
|
* @param endpointName - The endpoint key within the API.
|
|
434
550
|
* @param options - Optional fetch options.
|
|
435
|
-
* @returns A
|
|
436
|
-
*
|
|
437
|
-
* @example
|
|
438
|
-
* ```ts
|
|
439
|
-
* import { useFetchApi } from "katanakit-js";
|
|
440
|
-
*
|
|
441
|
-
* const result = await useFetchApi("pokeapi", "pokemonById", {
|
|
442
|
-
* method: "GET",
|
|
443
|
-
* params: { id: 25 },
|
|
444
|
-
* });
|
|
445
|
-
* if (result.ok) console.log(result.data);
|
|
446
|
-
* ```
|
|
551
|
+
* @returns A `FetchResult` with data or error.
|
|
447
552
|
*/
|
|
448
553
|
export async function useFetchApi(apiName, endpointName, options) {
|
|
449
554
|
return useFetch(apiName, endpointName, options);
|
|
@@ -454,37 +559,25 @@ export async function useFetchApi(apiName, endpointName, options) {
|
|
|
454
559
|
* @param apiName - The registered API key.
|
|
455
560
|
* @param endpointName - The endpoint key within the API.
|
|
456
561
|
* @param urlOptions - Optional URL building options.
|
|
457
|
-
* @returns A
|
|
562
|
+
* @returns A `FetchResult` with data or error.
|
|
458
563
|
*
|
|
459
564
|
* @example
|
|
460
565
|
* ```ts
|
|
461
566
|
* import { useGet } from "katanakit-js";
|
|
462
567
|
*
|
|
463
|
-
* const result = await useGet
|
|
464
|
-
* params: { id: 25 },
|
|
465
|
-
* });
|
|
568
|
+
* const result = await useGet("pokeapi", "pokemonById", { params: { id: 25 } });
|
|
466
569
|
* ```
|
|
467
570
|
*/
|
|
468
571
|
export async function useGet(apiName, endpointName, urlOptions) {
|
|
469
|
-
return
|
|
572
|
+
return FetchApiManager.getInstance().useGet(apiName, endpointName, urlOptions);
|
|
470
573
|
}
|
|
471
574
|
/**
|
|
472
|
-
* GET helper over a registered API endpoint.
|
|
473
|
-
* Alias for {@link useGet}.
|
|
575
|
+
* GET helper over a registered API endpoint. Alias for {@link useGet}.
|
|
474
576
|
*
|
|
475
577
|
* @param apiName - The registered API key.
|
|
476
578
|
* @param endpointName - The endpoint key within the API.
|
|
477
579
|
* @param urlOptions - Optional URL building options.
|
|
478
|
-
* @returns A
|
|
479
|
-
*
|
|
480
|
-
* @example
|
|
481
|
-
* ```ts
|
|
482
|
-
* import { useGetApi } from "katanakit-js";
|
|
483
|
-
*
|
|
484
|
-
* const result = await useGetApi<{ name: string }>("pokeapi", "pokemonById", {
|
|
485
|
-
* params: { id: 25 },
|
|
486
|
-
* });
|
|
487
|
-
* ```
|
|
580
|
+
* @returns A `FetchResult` with data or error.
|
|
488
581
|
*/
|
|
489
582
|
export async function useGetApi(apiName, endpointName, urlOptions) {
|
|
490
583
|
return useGet(apiName, endpointName, urlOptions);
|
|
@@ -496,7 +589,7 @@ export async function useGetApi(apiName, endpointName, urlOptions) {
|
|
|
496
589
|
* @param endpointName - The endpoint key within the API.
|
|
497
590
|
* @param body - Optional request body (auto-serialized to JSON unless raw).
|
|
498
591
|
* @param urlOptions - Optional URL building options.
|
|
499
|
-
* @returns A
|
|
592
|
+
* @returns A `FetchResult` with data or error.
|
|
500
593
|
*
|
|
501
594
|
* @example
|
|
502
595
|
* ```ts
|
|
@@ -506,11 +599,7 @@ export async function useGetApi(apiName, endpointName, urlOptions) {
|
|
|
506
599
|
* ```
|
|
507
600
|
*/
|
|
508
601
|
export async function usePost(apiName, endpointName, body, urlOptions) {
|
|
509
|
-
return
|
|
510
|
-
method: "POST",
|
|
511
|
-
...serializeBody(body),
|
|
512
|
-
...pickUrl(urlOptions),
|
|
513
|
-
});
|
|
602
|
+
return FetchApiManager.getInstance().usePost(apiName, endpointName, body, urlOptions);
|
|
514
603
|
}
|
|
515
604
|
/**
|
|
516
605
|
* PUT helper over a registered API endpoint.
|
|
@@ -519,21 +608,10 @@ export async function usePost(apiName, endpointName, body, urlOptions) {
|
|
|
519
608
|
* @param endpointName - The endpoint key within the API.
|
|
520
609
|
* @param body - Optional request body (auto-serialized to JSON unless raw).
|
|
521
610
|
* @param urlOptions - Optional URL building options.
|
|
522
|
-
* @returns A
|
|
523
|
-
*
|
|
524
|
-
* @example
|
|
525
|
-
* ```ts
|
|
526
|
-
* import { usePut } from "katanakit-js";
|
|
527
|
-
*
|
|
528
|
-
* const result = await usePut("pokeapi", "updatePokemon", { name: "Raichu" }, { params: { id: 25 } });
|
|
529
|
-
* ```
|
|
611
|
+
* @returns A `FetchResult` with data or error.
|
|
530
612
|
*/
|
|
531
613
|
export async function usePut(apiName, endpointName, body, urlOptions) {
|
|
532
|
-
return
|
|
533
|
-
method: "PUT",
|
|
534
|
-
...serializeBody(body),
|
|
535
|
-
...pickUrl(urlOptions),
|
|
536
|
-
});
|
|
614
|
+
return FetchApiManager.getInstance().usePut(apiName, endpointName, body, urlOptions);
|
|
537
615
|
}
|
|
538
616
|
/**
|
|
539
617
|
* PATCH helper over a registered API endpoint.
|
|
@@ -542,21 +620,10 @@ export async function usePut(apiName, endpointName, body, urlOptions) {
|
|
|
542
620
|
* @param endpointName - The endpoint key within the API.
|
|
543
621
|
* @param body - Optional request body (auto-serialized to JSON unless raw).
|
|
544
622
|
* @param urlOptions - Optional URL building options.
|
|
545
|
-
* @returns A
|
|
546
|
-
*
|
|
547
|
-
* @example
|
|
548
|
-
* ```ts
|
|
549
|
-
* import { usePatch } from "katanakit-js";
|
|
550
|
-
*
|
|
551
|
-
* const result = await usePatch("pokeapi", "updatePokemon", { name: "Raichu" }, { params: { id: 25 } });
|
|
552
|
-
* ```
|
|
623
|
+
* @returns A `FetchResult` with data or error.
|
|
553
624
|
*/
|
|
554
625
|
export async function usePatch(apiName, endpointName, body, urlOptions) {
|
|
555
|
-
return
|
|
556
|
-
method: "PATCH",
|
|
557
|
-
...serializeBody(body),
|
|
558
|
-
...pickUrl(urlOptions),
|
|
559
|
-
});
|
|
626
|
+
return FetchApiManager.getInstance().usePatch(apiName, endpointName, body, urlOptions);
|
|
560
627
|
}
|
|
561
628
|
/**
|
|
562
629
|
* DELETE helper over a registered API endpoint.
|
|
@@ -564,19 +631,9 @@ export async function usePatch(apiName, endpointName, body, urlOptions) {
|
|
|
564
631
|
* @param apiName - The registered API key.
|
|
565
632
|
* @param endpointName - The endpoint key within the API.
|
|
566
633
|
* @param urlOptions - Optional URL building options.
|
|
567
|
-
* @returns A
|
|
568
|
-
*
|
|
569
|
-
* @example
|
|
570
|
-
* ```ts
|
|
571
|
-
* import { useDelete } from "katanakit-js";
|
|
572
|
-
*
|
|
573
|
-
* const result = await useDelete("pokeapi", "deletePokemon", { params: { id: 25 } });
|
|
574
|
-
* ```
|
|
634
|
+
* @returns A `FetchResult` with data or error.
|
|
575
635
|
*/
|
|
576
636
|
export async function useDelete(apiName, endpointName, urlOptions) {
|
|
577
|
-
return
|
|
578
|
-
method: "DELETE",
|
|
579
|
-
...pickUrl(urlOptions),
|
|
580
|
-
});
|
|
637
|
+
return FetchApiManager.getInstance().useDelete(apiName, endpointName, urlOptions);
|
|
581
638
|
}
|
|
582
639
|
//# sourceMappingURL=http.service.js.map
|