@fgrzl/fetch 1.2.0 → 1.3.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/cjs/index.js +38 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/index.d.ts +115 -1
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -361,6 +361,93 @@ declare class NetworkError extends FetchError {
|
|
|
361
361
|
constructor(message: string, url: string, cause?: Error);
|
|
362
362
|
}
|
|
363
363
|
|
|
364
|
+
/**
|
|
365
|
+
* @fileoverview Query parameter utilities for FetchClient
|
|
366
|
+
*
|
|
367
|
+
* Provides utilities for building URL query strings from JavaScript objects
|
|
368
|
+
* with proper handling of arrays, undefined values, and URL encoding.
|
|
369
|
+
*/
|
|
370
|
+
/**
|
|
371
|
+
* Query parameter value types that can be converted to URL parameters.
|
|
372
|
+
* Arrays are handled specially with multiple parameter entries.
|
|
373
|
+
*/
|
|
374
|
+
type QueryValue = string | number | boolean | null | undefined | QueryValue[];
|
|
375
|
+
/**
|
|
376
|
+
* Object representing query parameters for URL construction.
|
|
377
|
+
*/
|
|
378
|
+
type QueryParams = Record<string, QueryValue>;
|
|
379
|
+
/**
|
|
380
|
+
* Builds a URL query string from a JavaScript object.
|
|
381
|
+
*
|
|
382
|
+
* Features:
|
|
383
|
+
* - ✅ Proper URL encoding via native URLSearchParams
|
|
384
|
+
* - ✅ Array handling with multiple parameter entries
|
|
385
|
+
* - ✅ Undefined value filtering (excluded from output)
|
|
386
|
+
* - ✅ Type coercion to strings for all values
|
|
387
|
+
*
|
|
388
|
+
* @param query - Object containing query parameters
|
|
389
|
+
* @returns URL-encoded query string (without leading '?')
|
|
390
|
+
*
|
|
391
|
+
* @example Basic usage:
|
|
392
|
+
* ```typescript
|
|
393
|
+
* buildQueryParams({ name: 'John', age: 30 })
|
|
394
|
+
* // → "name=John&age=30"
|
|
395
|
+
* ```
|
|
396
|
+
*
|
|
397
|
+
* @example Array handling:
|
|
398
|
+
* ```typescript
|
|
399
|
+
* buildQueryParams({ tags: ['typescript', 'javascript'], active: true })
|
|
400
|
+
* // → "tags=typescript&tags=javascript&active=true"
|
|
401
|
+
* ```
|
|
402
|
+
*
|
|
403
|
+
* @example Undefined filtering:
|
|
404
|
+
* ```typescript
|
|
405
|
+
* buildQueryParams({ name: 'John', email: undefined, age: null })
|
|
406
|
+
* // → "name=John&age=null" (undefined excluded, null converted to string)
|
|
407
|
+
* ```
|
|
408
|
+
*
|
|
409
|
+
* @example Real-world API usage:
|
|
410
|
+
* ```typescript
|
|
411
|
+
* const filters = {
|
|
412
|
+
* status: ['active', 'pending'],
|
|
413
|
+
* limit: 50,
|
|
414
|
+
* offset: 0,
|
|
415
|
+
* search: searchTerm || undefined // Conditionally included
|
|
416
|
+
* };
|
|
417
|
+
*
|
|
418
|
+
* const queryString = buildQueryParams(filters);
|
|
419
|
+
* // → "status=active&status=pending&limit=50&offset=0"
|
|
420
|
+
* // (search excluded if searchTerm is undefined)
|
|
421
|
+
* ```
|
|
422
|
+
*/
|
|
423
|
+
declare function buildQueryParams(query: QueryParams): string;
|
|
424
|
+
/**
|
|
425
|
+
* Appends query parameters to a URL, handling existing query strings properly.
|
|
426
|
+
*
|
|
427
|
+
* @param baseUrl - The base URL to append parameters to
|
|
428
|
+
* @param query - Object containing query parameters
|
|
429
|
+
* @returns Complete URL with query parameters appended
|
|
430
|
+
*
|
|
431
|
+
* @example Basic URL building:
|
|
432
|
+
* ```typescript
|
|
433
|
+
* appendQueryParams('/api/users', { limit: 10, active: true })
|
|
434
|
+
* // → "/api/users?limit=10&active=true"
|
|
435
|
+
* ```
|
|
436
|
+
*
|
|
437
|
+
* @example Existing query parameters:
|
|
438
|
+
* ```typescript
|
|
439
|
+
* appendQueryParams('/api/users?sort=name', { limit: 10 })
|
|
440
|
+
* // → "/api/users?sort=name&limit=10"
|
|
441
|
+
* ```
|
|
442
|
+
*
|
|
443
|
+
* @example Empty query object:
|
|
444
|
+
* ```typescript
|
|
445
|
+
* appendQueryParams('/api/users', {})
|
|
446
|
+
* // → "/api/users" (no change)
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
declare function appendQueryParams(baseUrl: string, query: QueryParams): string;
|
|
450
|
+
|
|
364
451
|
/**
|
|
365
452
|
* @fileoverview Authentication middleware types and configuration.
|
|
366
453
|
*/
|
|
@@ -1457,6 +1544,18 @@ declare function useBasicStack(client: FetchClient, config: {
|
|
|
1457
1544
|
* const activeUsers = await api.get('/api/users', { status: 'active', limit: 10 });
|
|
1458
1545
|
* ```
|
|
1459
1546
|
*
|
|
1547
|
+
* @example Set base URL for API-specific clients:
|
|
1548
|
+
* ```typescript
|
|
1549
|
+
* import api from '@fgrzl/fetch';
|
|
1550
|
+
*
|
|
1551
|
+
* // Configure base URL dynamically
|
|
1552
|
+
* api.setBaseUrl('https://api.example.com');
|
|
1553
|
+
*
|
|
1554
|
+
* // Now all relative URLs are prefixed automatically
|
|
1555
|
+
* const users = await api.get('/users'); // → GET https://api.example.com/users
|
|
1556
|
+
* const posts = await api.get('/posts'); // → GET https://api.example.com/posts
|
|
1557
|
+
* ```
|
|
1558
|
+
*
|
|
1460
1559
|
* @example Configure authentication:
|
|
1461
1560
|
* ```typescript
|
|
1462
1561
|
* import api from '@fgrzl/fetch';
|
|
@@ -1477,7 +1576,22 @@ declare function useBasicStack(client: FetchClient, config: {
|
|
|
1477
1576
|
* tokenProvider: () => getJWTToken()
|
|
1478
1577
|
* });
|
|
1479
1578
|
* ```
|
|
1579
|
+
*
|
|
1580
|
+
* @example Production-ready API client with base URL:
|
|
1581
|
+
* ```typescript
|
|
1582
|
+
* import { FetchClient, useProductionStack } from '@fgrzl/fetch';
|
|
1583
|
+
*
|
|
1584
|
+
* // One-liner production setup with base URL
|
|
1585
|
+
* const apiClient = useProductionStack(new FetchClient(), {
|
|
1586
|
+
* auth: { tokenProvider: () => getAuthToken() },
|
|
1587
|
+
* retry: { maxRetries: 3 },
|
|
1588
|
+
* logging: { level: 'info' }
|
|
1589
|
+
* }).setBaseUrl(process.env.API_BASE_URL || 'https://api.example.com');
|
|
1590
|
+
*
|
|
1591
|
+
* // Ready to use with full production features
|
|
1592
|
+
* const users = await apiClient.get('/users');
|
|
1593
|
+
* ```
|
|
1480
1594
|
*/
|
|
1481
1595
|
declare const api: FetchClient;
|
|
1482
1596
|
|
|
1483
|
-
export { type AuthTokenProvider, type AuthenticationOptions, type AuthorizationOptions, type CacheEntry, type CacheKeyGenerator, type CacheOptions, type CacheStorage, FetchClient, type FetchClientOptions, FetchError, type FetchResponse, HttpError, type FetchMiddleware as InterceptMiddleware, type LogLevel, type Logger, type LoggingOptions, NetworkError, type RateLimitAlgorithm, type RateLimitOptions, type RetryOptions, type UnauthorizedHandler, createAuthenticationMiddleware, createAuthorizationMiddleware, createCacheMiddleware, createLoggingMiddleware, createRateLimitMiddleware, createRetryMiddleware, api as default, useAuthentication, useAuthorization, useBasicStack, useCSRF, useCache, useDevelopmentStack, useLogging, useProductionStack, useRateLimit, useRetry };
|
|
1597
|
+
export { type AuthTokenProvider, type AuthenticationOptions, type AuthorizationOptions, type CacheEntry, type CacheKeyGenerator, type CacheOptions, type CacheStorage, FetchClient, type FetchClientOptions, FetchError, type FetchResponse, HttpError, type FetchMiddleware as InterceptMiddleware, type LogLevel, type Logger, type LoggingOptions, NetworkError, type QueryParams, type QueryValue, type RateLimitAlgorithm, type RateLimitOptions, type RetryOptions, type UnauthorizedHandler, appendQueryParams, buildQueryParams, createAuthenticationMiddleware, createAuthorizationMiddleware, createCacheMiddleware, createLoggingMiddleware, createRateLimitMiddleware, createRetryMiddleware, api as default, useAuthentication, useAuthorization, useBasicStack, useCSRF, useCache, useDevelopmentStack, useLogging, useProductionStack, useRateLimit, useRetry };
|
package/dist/index.js
CHANGED
|
@@ -1080,6 +1080,40 @@ var NetworkError = class extends FetchError {
|
|
|
1080
1080
|
}
|
|
1081
1081
|
};
|
|
1082
1082
|
|
|
1083
|
+
// src/client/query.ts
|
|
1084
|
+
function buildQueryParams(query) {
|
|
1085
|
+
const params = new URLSearchParams();
|
|
1086
|
+
for (const [key, value] of Object.entries(query)) {
|
|
1087
|
+
if (value !== void 0) {
|
|
1088
|
+
if (Array.isArray(value)) {
|
|
1089
|
+
value.forEach((item) => {
|
|
1090
|
+
if (item !== void 0) {
|
|
1091
|
+
params.append(key, String(item));
|
|
1092
|
+
}
|
|
1093
|
+
});
|
|
1094
|
+
} else {
|
|
1095
|
+
params.set(key, String(value));
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
return params.toString();
|
|
1100
|
+
}
|
|
1101
|
+
function appendQueryParams(baseUrl, query) {
|
|
1102
|
+
const queryString = buildQueryParams(query);
|
|
1103
|
+
if (!queryString) {
|
|
1104
|
+
return baseUrl;
|
|
1105
|
+
}
|
|
1106
|
+
const fragmentIndex = baseUrl.indexOf("#");
|
|
1107
|
+
if (fragmentIndex !== -1) {
|
|
1108
|
+
const urlPart = baseUrl.substring(0, fragmentIndex);
|
|
1109
|
+
const fragmentPart = baseUrl.substring(fragmentIndex);
|
|
1110
|
+
const separator2 = urlPart.includes("?") ? "&" : "?";
|
|
1111
|
+
return `${urlPart}${separator2}${queryString}${fragmentPart}`;
|
|
1112
|
+
}
|
|
1113
|
+
const separator = baseUrl.includes("?") ? "&" : "?";
|
|
1114
|
+
return `${baseUrl}${separator}${queryString}`;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1083
1117
|
// src/index.ts
|
|
1084
1118
|
var api = useProductionStack(
|
|
1085
1119
|
new FetchClient({
|
|
@@ -1114,6 +1148,8 @@ export {
|
|
|
1114
1148
|
FetchError,
|
|
1115
1149
|
HttpError,
|
|
1116
1150
|
NetworkError,
|
|
1151
|
+
appendQueryParams,
|
|
1152
|
+
buildQueryParams,
|
|
1117
1153
|
createAuthenticationMiddleware,
|
|
1118
1154
|
createAuthorizationMiddleware,
|
|
1119
1155
|
createCacheMiddleware,
|