@spoosh/core 0.8.2 → 0.9.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 +13 -10
- package/dist/index.d.mts +56 -55
- package/dist/index.d.ts +56 -55
- package/dist/index.js +81 -20
- package/dist/index.mjs +81 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,9 @@ import { createClient } from "@spoosh/core";
|
|
|
50
50
|
const api = createClient<ApiSchema>({
|
|
51
51
|
baseUrl: "/api",
|
|
52
52
|
});
|
|
53
|
+
|
|
54
|
+
// Import body wrappers for explicit serialization
|
|
55
|
+
import { json, form, urlencoded } from "@spoosh/core";
|
|
53
56
|
```
|
|
54
57
|
|
|
55
58
|
### Make API Calls
|
|
@@ -79,14 +82,14 @@ const { data: updated } = await api("users/:id").PUT({
|
|
|
79
82
|
// DELETE /api/users/123
|
|
80
83
|
await api("users/:id").DELETE({ params: { id: 123 } });
|
|
81
84
|
|
|
82
|
-
// POST with file upload (
|
|
85
|
+
// POST with file upload (using form() wrapper for multipart/form-data)
|
|
83
86
|
const { data: uploaded } = await api("upload").POST({
|
|
84
|
-
body: { file: myFile },
|
|
87
|
+
body: form({ file: myFile }),
|
|
85
88
|
});
|
|
86
89
|
|
|
87
|
-
// POST with form data
|
|
90
|
+
// POST with form data (using urlencoded() wrapper)
|
|
88
91
|
const { data: payment } = await api("payments").POST({
|
|
89
|
-
body: { amount: 1000, currency: "usd" },
|
|
92
|
+
body: urlencoded({ amount: 1000, currency: "usd" }),
|
|
90
93
|
});
|
|
91
94
|
```
|
|
92
95
|
|
|
@@ -172,12 +175,12 @@ const updatedContext = await applyMiddlewares(context, middlewares, "before");
|
|
|
172
175
|
|
|
173
176
|
## Schema Types
|
|
174
177
|
|
|
175
|
-
| Field | Description
|
|
176
|
-
| ------- |
|
|
177
|
-
| `data` | Response data type
|
|
178
|
-
| `body` | Request body type
|
|
179
|
-
| `query` | Query parameters type
|
|
180
|
-
| `error` | Typed error type
|
|
178
|
+
| Field | Description | Example |
|
|
179
|
+
| ------- | --------------------- | ------------------------------------------------ |
|
|
180
|
+
| `data` | Response data type | `GET: { data: User[] }` |
|
|
181
|
+
| `body` | Request body type | `POST: { data: User; body: CreateUserBody }` |
|
|
182
|
+
| `query` | Query parameters type | `GET: { data: User[]; query: { page: number } }` |
|
|
183
|
+
| `error` | Typed error type | `GET: { data: User; error: ApiError }` |
|
|
181
184
|
|
|
182
185
|
Path parameters are defined using `:param` syntax in the path key (e.g., `"users/:id"`).
|
|
183
186
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
2
|
+
type WriteMethod = "POST" | "PUT" | "PATCH" | "DELETE";
|
|
3
|
+
type Simplify<T> = {
|
|
4
|
+
[K in keyof T]: T[K];
|
|
5
|
+
} & {};
|
|
2
6
|
|
|
3
7
|
type MiddlewarePhase = "before" | "after";
|
|
4
8
|
type MiddlewareContext<TData = unknown, TError = unknown> = {
|
|
@@ -62,6 +66,20 @@ type SpooshOptionsExtra<TData = unknown, TError = unknown> = {
|
|
|
62
66
|
middlewares?: SpooshMiddleware<TData, TError>[];
|
|
63
67
|
};
|
|
64
68
|
|
|
69
|
+
type SpooshBody<T = unknown> = {
|
|
70
|
+
readonly __spooshBody: true;
|
|
71
|
+
readonly kind: "form" | "json" | "urlencoded";
|
|
72
|
+
readonly value: T;
|
|
73
|
+
};
|
|
74
|
+
declare function isSpooshBody(value: unknown): value is SpooshBody;
|
|
75
|
+
declare function form<T>(value: T): SpooshBody<T>;
|
|
76
|
+
declare function json<T>(value: T): SpooshBody<T>;
|
|
77
|
+
declare function urlencoded<T>(value: T): SpooshBody<T>;
|
|
78
|
+
declare function resolveRequestBody(rawBody: unknown): {
|
|
79
|
+
body: BodyInit;
|
|
80
|
+
headers?: Record<string, string>;
|
|
81
|
+
} | undefined;
|
|
82
|
+
|
|
65
83
|
type RetryConfig = {
|
|
66
84
|
retries?: number | false;
|
|
67
85
|
retryDelay?: number;
|
|
@@ -76,9 +94,9 @@ type BaseRequestOptions$1 = {
|
|
|
76
94
|
signal?: AbortSignal;
|
|
77
95
|
};
|
|
78
96
|
type BodyOption$1<TBody> = [TBody] extends [never] ? object : undefined extends TBody ? {
|
|
79
|
-
body?: Exclude<TBody, undefined
|
|
97
|
+
body?: Exclude<TBody, undefined> | SpooshBody<Exclude<TBody, undefined>>;
|
|
80
98
|
} : {
|
|
81
|
-
body: TBody
|
|
99
|
+
body: TBody | SpooshBody<TBody>;
|
|
82
100
|
};
|
|
83
101
|
type QueryOption$1<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
|
|
84
102
|
query?: Exclude<TQuery, undefined>;
|
|
@@ -825,10 +843,27 @@ type ExtractParamNames<T extends string> = T extends `${string}:${infer Param}/$
|
|
|
825
843
|
* ```
|
|
826
844
|
*/
|
|
827
845
|
type HasParams<T extends string> = T extends `${string}:${string}` ? true : false;
|
|
846
|
+
/**
|
|
847
|
+
* Extract paths that have GET methods.
|
|
848
|
+
*/
|
|
849
|
+
type ReadPaths<TSchema> = {
|
|
850
|
+
[K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
|
|
851
|
+
}[keyof TSchema & string];
|
|
852
|
+
/**
|
|
853
|
+
* Extract paths that have write methods (POST, PUT, PATCH, DELETE).
|
|
854
|
+
*/
|
|
855
|
+
type WritePaths<TSchema> = {
|
|
856
|
+
[K in keyof TSchema & string]: Extract<keyof TSchema[K], WriteMethod> extends never ? never : K;
|
|
857
|
+
}[keyof TSchema & string];
|
|
858
|
+
/**
|
|
859
|
+
* Check if a schema path has a GET method.
|
|
860
|
+
*/
|
|
861
|
+
type HasReadMethod<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? true : false : false : false;
|
|
862
|
+
/**
|
|
863
|
+
* Check if a schema path has any write methods.
|
|
864
|
+
*/
|
|
865
|
+
type HasWriteMethod<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? WriteMethod extends never ? false : Extract<keyof TSchema[TKey], WriteMethod> extends never ? false : true : false : false;
|
|
828
866
|
|
|
829
|
-
type Simplify$1<T> = {
|
|
830
|
-
[K in keyof T]: T[K];
|
|
831
|
-
} & {};
|
|
832
867
|
type IsNever<T> = [T] extends [never] ? true : false;
|
|
833
868
|
type EndpointRequestOptions<TEndpoint, TPath extends string> = (IsNever<ExtractBody$1<TEndpoint>> extends true ? object : {
|
|
834
869
|
body: ExtractBody$1<TEndpoint>;
|
|
@@ -837,14 +872,10 @@ type EndpointRequestOptions<TEndpoint, TPath extends string> = (IsNever<ExtractB
|
|
|
837
872
|
}) & (HasParams<TPath> extends true ? {
|
|
838
873
|
params: Record<ExtractParamNames<TPath>, string | number>;
|
|
839
874
|
} : object);
|
|
840
|
-
type EndpointMethodFn<TEndpoint, TPath extends string> = (options?: Simplify
|
|
841
|
-
type
|
|
875
|
+
type EndpointMethodFn<TEndpoint, TPath extends string> = (options?: Simplify<EndpointRequestOptions<TEndpoint, TPath>>) => Promise<SpooshResponse<ExtractData<TEndpoint>, unknown, EndpointRequestOptions<TEndpoint, TPath>>>;
|
|
876
|
+
type ReadPathMethods$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? Simplify<{
|
|
842
877
|
GET: EndpointMethodFn<TSchema[TKey]["GET"], TPath>;
|
|
843
878
|
}> : never : never : never;
|
|
844
|
-
type ReadPaths$1<TSchema> = {
|
|
845
|
-
[K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
|
|
846
|
-
}[keyof TSchema & string];
|
|
847
|
-
type HasGetMethod$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? true : false : false : false;
|
|
848
879
|
/**
|
|
849
880
|
* Schema navigation helper for plugins that need type-safe API schema access.
|
|
850
881
|
*
|
|
@@ -858,7 +889,7 @@ type HasGetMethod$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TP
|
|
|
858
889
|
* ```ts
|
|
859
890
|
* // Define your plugin's callback type
|
|
860
891
|
* type MyCallbackFn<TSchema = unknown> = (
|
|
861
|
-
* api:
|
|
892
|
+
* api: ReadSchemaHelper<TSchema>
|
|
862
893
|
* ) => unknown;
|
|
863
894
|
*
|
|
864
895
|
* // Usage in plugin options
|
|
@@ -886,25 +917,17 @@ type HasGetMethod$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TP
|
|
|
886
917
|
* });
|
|
887
918
|
* ```
|
|
888
919
|
*/
|
|
889
|
-
type
|
|
890
|
-
type
|
|
891
|
-
|
|
892
|
-
[M in MutationMethod$1 as M extends keyof TSchema[TKey] ? M : never]: M extends keyof TSchema[TKey] ? EndpointMethodFn<TSchema[TKey][M], TPath> : never;
|
|
920
|
+
type ReadSchemaHelper<TSchema> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => HasReadMethod<TSchema, TPath> extends true ? ReadPathMethods$1<TSchema, TPath> : never;
|
|
921
|
+
type WritePathMethods$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? Simplify<{
|
|
922
|
+
[M in WriteMethod as M extends keyof TSchema[TKey] ? M : never]: M extends keyof TSchema[TKey] ? EndpointMethodFn<TSchema[TKey][M], TPath> : never;
|
|
893
923
|
}> : never : never;
|
|
894
|
-
type WritePaths$1<TSchema> = {
|
|
895
|
-
[K in keyof TSchema & string]: Extract<keyof TSchema[K], MutationMethod$1> extends never ? never : K;
|
|
896
|
-
}[keyof TSchema & string];
|
|
897
|
-
type HasMutationMethod$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? MutationMethod$1 extends never ? false : Extract<keyof TSchema[TKey], MutationMethod$1> extends never ? false : true : false : false;
|
|
898
924
|
/**
|
|
899
925
|
* Schema navigation helper for plugins that need type-safe API schema access for mutations.
|
|
900
926
|
*
|
|
901
|
-
* Similar to
|
|
927
|
+
* Similar to ReadSchemaHelper but exposes write methods (POST, PUT, PATCH, DELETE).
|
|
902
928
|
*/
|
|
903
|
-
type
|
|
929
|
+
type WriteSchemaHelper<TSchema> = <TPath extends WritePaths<TSchema> | (string & {})>(path: TPath) => HasWriteMethod<TSchema, TPath> extends true ? WritePathMethods$1<TSchema, TPath> : never;
|
|
904
930
|
|
|
905
|
-
type Simplify<T> = {
|
|
906
|
-
[K in keyof T]: T[K];
|
|
907
|
-
} & {};
|
|
908
931
|
/**
|
|
909
932
|
* Base request options available on all methods.
|
|
910
933
|
*/
|
|
@@ -941,9 +964,9 @@ type IsQueryRequired<T> = T extends {
|
|
|
941
964
|
* Build the options type for a method.
|
|
942
965
|
*/
|
|
943
966
|
type BodyOption<T> = [ExtractBody<T>] extends [never] ? {} : IsBodyRequired<T> extends true ? {
|
|
944
|
-
body: ExtractBody<T
|
|
967
|
+
body: ExtractBody<T> | SpooshBody<ExtractBody<T>>;
|
|
945
968
|
} : {
|
|
946
|
-
body?: ExtractBody<T
|
|
969
|
+
body?: ExtractBody<T> | SpooshBody<ExtractBody<T>>;
|
|
947
970
|
};
|
|
948
971
|
type QueryOption<T> = [ExtractQuery<T>] extends [never] ? {} : IsQueryRequired<T> extends true ? {
|
|
949
972
|
query: ExtractQuery<T>;
|
|
@@ -1014,47 +1037,23 @@ type SpooshClient<TSchema, TDefaultError = unknown> = <TPath extends SchemaPaths
|
|
|
1014
1037
|
type ReadPathMethods<TSchema, TPath extends string, TDefaultError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? Simplify<{
|
|
1015
1038
|
GET: MethodFn<TSchema[TKey]["GET"], TDefaultError, TPath>;
|
|
1016
1039
|
}> : never : never : never;
|
|
1017
|
-
/**
|
|
1018
|
-
* Check if a schema path has a GET method.
|
|
1019
|
-
*/
|
|
1020
|
-
type HasGetMethod<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? true : false : false : false;
|
|
1021
|
-
/**
|
|
1022
|
-
* Extract paths that have GET methods.
|
|
1023
|
-
*/
|
|
1024
|
-
type ReadPaths<TSchema> = {
|
|
1025
|
-
[K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
|
|
1026
|
-
}[keyof TSchema & string];
|
|
1027
1040
|
/**
|
|
1028
1041
|
* A read-only API client that only exposes GET methods.
|
|
1029
1042
|
* Used by useRead and injectRead hooks.
|
|
1030
1043
|
*/
|
|
1031
|
-
type ReadClient<TSchema, TDefaultError = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) =>
|
|
1032
|
-
/**
|
|
1033
|
-
* Mutation methods (non-GET).
|
|
1034
|
-
*/
|
|
1035
|
-
type MutationMethod = "POST" | "PUT" | "PATCH" | "DELETE";
|
|
1044
|
+
type ReadClient<TSchema, TDefaultError = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => HasReadMethod<TSchema, TPath> extends true ? ReadPathMethods<TSchema, TPath, TDefaultError> : never;
|
|
1036
1045
|
/**
|
|
1037
1046
|
* Write-only client type that only exposes mutation methods (POST, PUT, PATCH, DELETE).
|
|
1038
1047
|
* Used by useWrite/injectWrite hooks to ensure only mutation operations are selected.
|
|
1039
1048
|
*/
|
|
1040
1049
|
type WritePathMethods<TSchema, TPath extends string, TDefaultError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? Simplify<{
|
|
1041
|
-
[M in
|
|
1050
|
+
[M in WriteMethod as M extends keyof TSchema[TKey] ? M : never]: M extends keyof TSchema[TKey] ? MethodFn<TSchema[TKey][M], TDefaultError, TPath> : never;
|
|
1042
1051
|
}> : never : never;
|
|
1043
|
-
/**
|
|
1044
|
-
* Check if a schema path has any mutation methods.
|
|
1045
|
-
*/
|
|
1046
|
-
type HasMutationMethod<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? MutationMethod extends never ? false : Extract<keyof TSchema[TKey], MutationMethod> extends never ? false : true : false : false;
|
|
1047
|
-
/**
|
|
1048
|
-
* Extract paths that have mutation methods.
|
|
1049
|
-
*/
|
|
1050
|
-
type WritePaths<TSchema> = {
|
|
1051
|
-
[K in keyof TSchema & string]: Extract<keyof TSchema[K], MutationMethod> extends never ? never : K;
|
|
1052
|
-
}[keyof TSchema & string];
|
|
1053
1052
|
/**
|
|
1054
1053
|
* A write-only API client that only exposes mutation methods (POST, PUT, PATCH, DELETE).
|
|
1055
1054
|
* Used by useWrite and injectWrite hooks.
|
|
1056
1055
|
*/
|
|
1057
|
-
type WriteClient<TSchema, TDefaultError = unknown> = <TPath extends WritePaths<TSchema> | (string & {})>(path: TPath) =>
|
|
1056
|
+
type WriteClient<TSchema, TDefaultError = unknown> = <TPath extends WritePaths<TSchema> | (string & {})>(path: TPath) => HasWriteMethod<TSchema, TPath> extends true ? WritePathMethods<TSchema, TPath, TDefaultError> : never;
|
|
1058
1057
|
|
|
1059
1058
|
type PluginArray = readonly SpooshPlugin<PluginTypeConfig>[];
|
|
1060
1059
|
interface SpooshConfig<TPlugins extends PluginArray = PluginArray> {
|
|
@@ -1334,6 +1333,8 @@ declare function createClient<TSchema, TDefaultError = unknown>(config: SpooshCl
|
|
|
1334
1333
|
|
|
1335
1334
|
declare function buildUrl(baseUrl: string, path: string[], query?: Record<string, string | number | boolean | undefined>): string;
|
|
1336
1335
|
|
|
1336
|
+
declare function __DEV__(): boolean;
|
|
1337
|
+
|
|
1337
1338
|
/**
|
|
1338
1339
|
* Generate cache tags from URL path segments.
|
|
1339
1340
|
* e.g., ['posts', '1'] → ['posts', 'posts/1']
|
|
@@ -1608,4 +1609,4 @@ type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
|
|
|
1608
1609
|
};
|
|
1609
1610
|
declare function createInfiniteReadController<TData, TItem, TError, TRequest extends InfiniteRequestOptions = InfiniteRequestOptions>(options: CreateInfiniteReadOptions<TData, TItem, TError, TRequest>): InfiniteReadController<TData, TItem, TError>;
|
|
1610
1611
|
|
|
1611
|
-
export { type AnyRequestOptions, type ApiSchema, type BuiltInEvents, type CacheEntry, type CacheEntryWithKey, type CapturedCall, type SpooshClientConfig as ClientConfig, type ComputeRequestOptions, type CoreRequestOptionsBase, type CreateInfiniteReadOptions, type CreateOperationOptions, type DataAwareCallback, type DataAwareTransform, type EventEmitter, type ExtractBody$1 as ExtractBody, type ExtractData, type ExtractError, type ExtractMethodOptions, type ExtractParamNames, type ExtractQuery$1 as ExtractQuery, type FetchDirection, type FetchExecutor, type FindMatchingKey, HTTP_METHODS, type HasParams, type HeadersInitOrGetter, type HttpMethod, type HttpMethodKey, type InfiniteReadController, type InfiniteReadState, type InfiniteRequestOptions, type InstanceApiContext, type InstanceApiResolvers, type InstancePluginExecutor, type LifecyclePhase, type MergePluginInstanceApi, type MergePluginOptions, type MergePluginResults, type MethodOptionsMap, type MiddlewareContext, type MiddlewareHandler, type MiddlewarePhase, type
|
|
1612
|
+
export { type AnyRequestOptions, type ApiSchema, type BuiltInEvents, type CacheEntry, type CacheEntryWithKey, type CapturedCall, type SpooshClientConfig as ClientConfig, type ComputeRequestOptions, type CoreRequestOptionsBase, type CreateInfiniteReadOptions, type CreateOperationOptions, type DataAwareCallback, type DataAwareTransform, type EventEmitter, type ExtractBody$1 as ExtractBody, type ExtractData, type ExtractError, type ExtractMethodOptions, type ExtractParamNames, type ExtractQuery$1 as ExtractQuery, type FetchDirection, type FetchExecutor, type FindMatchingKey, HTTP_METHODS, type HasParams, type HasReadMethod, type HasWriteMethod, type HeadersInitOrGetter, type HttpMethod, type HttpMethodKey, type InfiniteReadController, type InfiniteReadState, type InfiniteRequestOptions, type InstanceApiContext, type InstanceApiResolvers, type InstancePluginExecutor, type LifecyclePhase, type MergePluginInstanceApi, type MergePluginOptions, type MergePluginResults, type MethodOptionsMap, type MiddlewareContext, type MiddlewareHandler, type MiddlewarePhase, type OperationController, type OperationState, type OperationType, type PageContext, type PluginAccessor, type PluginArray, type PluginContext, type PluginContextInput, type PluginExecutor, type PluginExportsRegistry, type PluginFactory, type PluginHandler, type PluginLifecycle, type PluginMiddleware, type PluginRegistry, type PluginResolvers, type PluginResponseHandler, type PluginResultResolvers, type PluginTypeConfig, type PluginUpdateHandler, type ReadClient, type ReadPaths, type ReadSchemaHelper, type RefetchEvent, type RequestOptions$1 as RequestOptions, type ResolveInstanceApi, type ResolveResultTypes, type ResolveSchemaTypes, type ResolveTypes, type ResolverContext, type RetryConfig, type RouteToPath, type SchemaPaths, type SelectedEndpoint, type SelectorFunction, type SelectorResult, type Simplify, Spoosh, type SpooshBody, type SpooshClient, type SpooshConfig, type SpooshInstance, type SpooshMiddleware, type SpooshOptions, type SpooshOptionsExtra, type SpooshPlugin, type SpooshResponse, type SpooshSchema, type StateManager, type TagMode, type TagOptions, type WriteClient, type WriteMethod, type WritePaths, type WriteSchemaHelper, __DEV__, applyMiddlewares, buildUrl, composeMiddlewares, containsFile, createClient, createEventEmitter, createInfiniteReadController, createInitialState, createMiddleware, createOperationController, createPluginExecutor, createPluginRegistry, createProxyHandler, createSelectorProxy, createStateManager, executeFetch, extractMethodFromSelector, extractPathFromSelector, form, generateTags, getContentType, isJsonBody, isSpooshBody, json, mergeHeaders, objectToFormData, objectToUrlEncoded, resolveHeadersToRecord, resolvePath, resolveRequestBody, resolveTags, setHeaders, sortObjectKeys, urlencoded };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
2
|
+
type WriteMethod = "POST" | "PUT" | "PATCH" | "DELETE";
|
|
3
|
+
type Simplify<T> = {
|
|
4
|
+
[K in keyof T]: T[K];
|
|
5
|
+
} & {};
|
|
2
6
|
|
|
3
7
|
type MiddlewarePhase = "before" | "after";
|
|
4
8
|
type MiddlewareContext<TData = unknown, TError = unknown> = {
|
|
@@ -62,6 +66,20 @@ type SpooshOptionsExtra<TData = unknown, TError = unknown> = {
|
|
|
62
66
|
middlewares?: SpooshMiddleware<TData, TError>[];
|
|
63
67
|
};
|
|
64
68
|
|
|
69
|
+
type SpooshBody<T = unknown> = {
|
|
70
|
+
readonly __spooshBody: true;
|
|
71
|
+
readonly kind: "form" | "json" | "urlencoded";
|
|
72
|
+
readonly value: T;
|
|
73
|
+
};
|
|
74
|
+
declare function isSpooshBody(value: unknown): value is SpooshBody;
|
|
75
|
+
declare function form<T>(value: T): SpooshBody<T>;
|
|
76
|
+
declare function json<T>(value: T): SpooshBody<T>;
|
|
77
|
+
declare function urlencoded<T>(value: T): SpooshBody<T>;
|
|
78
|
+
declare function resolveRequestBody(rawBody: unknown): {
|
|
79
|
+
body: BodyInit;
|
|
80
|
+
headers?: Record<string, string>;
|
|
81
|
+
} | undefined;
|
|
82
|
+
|
|
65
83
|
type RetryConfig = {
|
|
66
84
|
retries?: number | false;
|
|
67
85
|
retryDelay?: number;
|
|
@@ -76,9 +94,9 @@ type BaseRequestOptions$1 = {
|
|
|
76
94
|
signal?: AbortSignal;
|
|
77
95
|
};
|
|
78
96
|
type BodyOption$1<TBody> = [TBody] extends [never] ? object : undefined extends TBody ? {
|
|
79
|
-
body?: Exclude<TBody, undefined
|
|
97
|
+
body?: Exclude<TBody, undefined> | SpooshBody<Exclude<TBody, undefined>>;
|
|
80
98
|
} : {
|
|
81
|
-
body: TBody
|
|
99
|
+
body: TBody | SpooshBody<TBody>;
|
|
82
100
|
};
|
|
83
101
|
type QueryOption$1<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
|
|
84
102
|
query?: Exclude<TQuery, undefined>;
|
|
@@ -825,10 +843,27 @@ type ExtractParamNames<T extends string> = T extends `${string}:${infer Param}/$
|
|
|
825
843
|
* ```
|
|
826
844
|
*/
|
|
827
845
|
type HasParams<T extends string> = T extends `${string}:${string}` ? true : false;
|
|
846
|
+
/**
|
|
847
|
+
* Extract paths that have GET methods.
|
|
848
|
+
*/
|
|
849
|
+
type ReadPaths<TSchema> = {
|
|
850
|
+
[K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
|
|
851
|
+
}[keyof TSchema & string];
|
|
852
|
+
/**
|
|
853
|
+
* Extract paths that have write methods (POST, PUT, PATCH, DELETE).
|
|
854
|
+
*/
|
|
855
|
+
type WritePaths<TSchema> = {
|
|
856
|
+
[K in keyof TSchema & string]: Extract<keyof TSchema[K], WriteMethod> extends never ? never : K;
|
|
857
|
+
}[keyof TSchema & string];
|
|
858
|
+
/**
|
|
859
|
+
* Check if a schema path has a GET method.
|
|
860
|
+
*/
|
|
861
|
+
type HasReadMethod<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? true : false : false : false;
|
|
862
|
+
/**
|
|
863
|
+
* Check if a schema path has any write methods.
|
|
864
|
+
*/
|
|
865
|
+
type HasWriteMethod<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? WriteMethod extends never ? false : Extract<keyof TSchema[TKey], WriteMethod> extends never ? false : true : false : false;
|
|
828
866
|
|
|
829
|
-
type Simplify$1<T> = {
|
|
830
|
-
[K in keyof T]: T[K];
|
|
831
|
-
} & {};
|
|
832
867
|
type IsNever<T> = [T] extends [never] ? true : false;
|
|
833
868
|
type EndpointRequestOptions<TEndpoint, TPath extends string> = (IsNever<ExtractBody$1<TEndpoint>> extends true ? object : {
|
|
834
869
|
body: ExtractBody$1<TEndpoint>;
|
|
@@ -837,14 +872,10 @@ type EndpointRequestOptions<TEndpoint, TPath extends string> = (IsNever<ExtractB
|
|
|
837
872
|
}) & (HasParams<TPath> extends true ? {
|
|
838
873
|
params: Record<ExtractParamNames<TPath>, string | number>;
|
|
839
874
|
} : object);
|
|
840
|
-
type EndpointMethodFn<TEndpoint, TPath extends string> = (options?: Simplify
|
|
841
|
-
type
|
|
875
|
+
type EndpointMethodFn<TEndpoint, TPath extends string> = (options?: Simplify<EndpointRequestOptions<TEndpoint, TPath>>) => Promise<SpooshResponse<ExtractData<TEndpoint>, unknown, EndpointRequestOptions<TEndpoint, TPath>>>;
|
|
876
|
+
type ReadPathMethods$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? Simplify<{
|
|
842
877
|
GET: EndpointMethodFn<TSchema[TKey]["GET"], TPath>;
|
|
843
878
|
}> : never : never : never;
|
|
844
|
-
type ReadPaths$1<TSchema> = {
|
|
845
|
-
[K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
|
|
846
|
-
}[keyof TSchema & string];
|
|
847
|
-
type HasGetMethod$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? true : false : false : false;
|
|
848
879
|
/**
|
|
849
880
|
* Schema navigation helper for plugins that need type-safe API schema access.
|
|
850
881
|
*
|
|
@@ -858,7 +889,7 @@ type HasGetMethod$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TP
|
|
|
858
889
|
* ```ts
|
|
859
890
|
* // Define your plugin's callback type
|
|
860
891
|
* type MyCallbackFn<TSchema = unknown> = (
|
|
861
|
-
* api:
|
|
892
|
+
* api: ReadSchemaHelper<TSchema>
|
|
862
893
|
* ) => unknown;
|
|
863
894
|
*
|
|
864
895
|
* // Usage in plugin options
|
|
@@ -886,25 +917,17 @@ type HasGetMethod$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TP
|
|
|
886
917
|
* });
|
|
887
918
|
* ```
|
|
888
919
|
*/
|
|
889
|
-
type
|
|
890
|
-
type
|
|
891
|
-
|
|
892
|
-
[M in MutationMethod$1 as M extends keyof TSchema[TKey] ? M : never]: M extends keyof TSchema[TKey] ? EndpointMethodFn<TSchema[TKey][M], TPath> : never;
|
|
920
|
+
type ReadSchemaHelper<TSchema> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => HasReadMethod<TSchema, TPath> extends true ? ReadPathMethods$1<TSchema, TPath> : never;
|
|
921
|
+
type WritePathMethods$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? Simplify<{
|
|
922
|
+
[M in WriteMethod as M extends keyof TSchema[TKey] ? M : never]: M extends keyof TSchema[TKey] ? EndpointMethodFn<TSchema[TKey][M], TPath> : never;
|
|
893
923
|
}> : never : never;
|
|
894
|
-
type WritePaths$1<TSchema> = {
|
|
895
|
-
[K in keyof TSchema & string]: Extract<keyof TSchema[K], MutationMethod$1> extends never ? never : K;
|
|
896
|
-
}[keyof TSchema & string];
|
|
897
|
-
type HasMutationMethod$1<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? MutationMethod$1 extends never ? false : Extract<keyof TSchema[TKey], MutationMethod$1> extends never ? false : true : false : false;
|
|
898
924
|
/**
|
|
899
925
|
* Schema navigation helper for plugins that need type-safe API schema access for mutations.
|
|
900
926
|
*
|
|
901
|
-
* Similar to
|
|
927
|
+
* Similar to ReadSchemaHelper but exposes write methods (POST, PUT, PATCH, DELETE).
|
|
902
928
|
*/
|
|
903
|
-
type
|
|
929
|
+
type WriteSchemaHelper<TSchema> = <TPath extends WritePaths<TSchema> | (string & {})>(path: TPath) => HasWriteMethod<TSchema, TPath> extends true ? WritePathMethods$1<TSchema, TPath> : never;
|
|
904
930
|
|
|
905
|
-
type Simplify<T> = {
|
|
906
|
-
[K in keyof T]: T[K];
|
|
907
|
-
} & {};
|
|
908
931
|
/**
|
|
909
932
|
* Base request options available on all methods.
|
|
910
933
|
*/
|
|
@@ -941,9 +964,9 @@ type IsQueryRequired<T> = T extends {
|
|
|
941
964
|
* Build the options type for a method.
|
|
942
965
|
*/
|
|
943
966
|
type BodyOption<T> = [ExtractBody<T>] extends [never] ? {} : IsBodyRequired<T> extends true ? {
|
|
944
|
-
body: ExtractBody<T
|
|
967
|
+
body: ExtractBody<T> | SpooshBody<ExtractBody<T>>;
|
|
945
968
|
} : {
|
|
946
|
-
body?: ExtractBody<T
|
|
969
|
+
body?: ExtractBody<T> | SpooshBody<ExtractBody<T>>;
|
|
947
970
|
};
|
|
948
971
|
type QueryOption<T> = [ExtractQuery<T>] extends [never] ? {} : IsQueryRequired<T> extends true ? {
|
|
949
972
|
query: ExtractQuery<T>;
|
|
@@ -1014,47 +1037,23 @@ type SpooshClient<TSchema, TDefaultError = unknown> = <TPath extends SchemaPaths
|
|
|
1014
1037
|
type ReadPathMethods<TSchema, TPath extends string, TDefaultError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? Simplify<{
|
|
1015
1038
|
GET: MethodFn<TSchema[TKey]["GET"], TDefaultError, TPath>;
|
|
1016
1039
|
}> : never : never : never;
|
|
1017
|
-
/**
|
|
1018
|
-
* Check if a schema path has a GET method.
|
|
1019
|
-
*/
|
|
1020
|
-
type HasGetMethod<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? true : false : false : false;
|
|
1021
|
-
/**
|
|
1022
|
-
* Extract paths that have GET methods.
|
|
1023
|
-
*/
|
|
1024
|
-
type ReadPaths<TSchema> = {
|
|
1025
|
-
[K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
|
|
1026
|
-
}[keyof TSchema & string];
|
|
1027
1040
|
/**
|
|
1028
1041
|
* A read-only API client that only exposes GET methods.
|
|
1029
1042
|
* Used by useRead and injectRead hooks.
|
|
1030
1043
|
*/
|
|
1031
|
-
type ReadClient<TSchema, TDefaultError = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) =>
|
|
1032
|
-
/**
|
|
1033
|
-
* Mutation methods (non-GET).
|
|
1034
|
-
*/
|
|
1035
|
-
type MutationMethod = "POST" | "PUT" | "PATCH" | "DELETE";
|
|
1044
|
+
type ReadClient<TSchema, TDefaultError = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => HasReadMethod<TSchema, TPath> extends true ? ReadPathMethods<TSchema, TPath, TDefaultError> : never;
|
|
1036
1045
|
/**
|
|
1037
1046
|
* Write-only client type that only exposes mutation methods (POST, PUT, PATCH, DELETE).
|
|
1038
1047
|
* Used by useWrite/injectWrite hooks to ensure only mutation operations are selected.
|
|
1039
1048
|
*/
|
|
1040
1049
|
type WritePathMethods<TSchema, TPath extends string, TDefaultError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? Simplify<{
|
|
1041
|
-
[M in
|
|
1050
|
+
[M in WriteMethod as M extends keyof TSchema[TKey] ? M : never]: M extends keyof TSchema[TKey] ? MethodFn<TSchema[TKey][M], TDefaultError, TPath> : never;
|
|
1042
1051
|
}> : never : never;
|
|
1043
|
-
/**
|
|
1044
|
-
* Check if a schema path has any mutation methods.
|
|
1045
|
-
*/
|
|
1046
|
-
type HasMutationMethod<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? MutationMethod extends never ? false : Extract<keyof TSchema[TKey], MutationMethod> extends never ? false : true : false : false;
|
|
1047
|
-
/**
|
|
1048
|
-
* Extract paths that have mutation methods.
|
|
1049
|
-
*/
|
|
1050
|
-
type WritePaths<TSchema> = {
|
|
1051
|
-
[K in keyof TSchema & string]: Extract<keyof TSchema[K], MutationMethod> extends never ? never : K;
|
|
1052
|
-
}[keyof TSchema & string];
|
|
1053
1052
|
/**
|
|
1054
1053
|
* A write-only API client that only exposes mutation methods (POST, PUT, PATCH, DELETE).
|
|
1055
1054
|
* Used by useWrite and injectWrite hooks.
|
|
1056
1055
|
*/
|
|
1057
|
-
type WriteClient<TSchema, TDefaultError = unknown> = <TPath extends WritePaths<TSchema> | (string & {})>(path: TPath) =>
|
|
1056
|
+
type WriteClient<TSchema, TDefaultError = unknown> = <TPath extends WritePaths<TSchema> | (string & {})>(path: TPath) => HasWriteMethod<TSchema, TPath> extends true ? WritePathMethods<TSchema, TPath, TDefaultError> : never;
|
|
1058
1057
|
|
|
1059
1058
|
type PluginArray = readonly SpooshPlugin<PluginTypeConfig>[];
|
|
1060
1059
|
interface SpooshConfig<TPlugins extends PluginArray = PluginArray> {
|
|
@@ -1334,6 +1333,8 @@ declare function createClient<TSchema, TDefaultError = unknown>(config: SpooshCl
|
|
|
1334
1333
|
|
|
1335
1334
|
declare function buildUrl(baseUrl: string, path: string[], query?: Record<string, string | number | boolean | undefined>): string;
|
|
1336
1335
|
|
|
1336
|
+
declare function __DEV__(): boolean;
|
|
1337
|
+
|
|
1337
1338
|
/**
|
|
1338
1339
|
* Generate cache tags from URL path segments.
|
|
1339
1340
|
* e.g., ['posts', '1'] → ['posts', 'posts/1']
|
|
@@ -1608,4 +1609,4 @@ type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
|
|
|
1608
1609
|
};
|
|
1609
1610
|
declare function createInfiniteReadController<TData, TItem, TError, TRequest extends InfiniteRequestOptions = InfiniteRequestOptions>(options: CreateInfiniteReadOptions<TData, TItem, TError, TRequest>): InfiniteReadController<TData, TItem, TError>;
|
|
1610
1611
|
|
|
1611
|
-
export { type AnyRequestOptions, type ApiSchema, type BuiltInEvents, type CacheEntry, type CacheEntryWithKey, type CapturedCall, type SpooshClientConfig as ClientConfig, type ComputeRequestOptions, type CoreRequestOptionsBase, type CreateInfiniteReadOptions, type CreateOperationOptions, type DataAwareCallback, type DataAwareTransform, type EventEmitter, type ExtractBody$1 as ExtractBody, type ExtractData, type ExtractError, type ExtractMethodOptions, type ExtractParamNames, type ExtractQuery$1 as ExtractQuery, type FetchDirection, type FetchExecutor, type FindMatchingKey, HTTP_METHODS, type HasParams, type HeadersInitOrGetter, type HttpMethod, type HttpMethodKey, type InfiniteReadController, type InfiniteReadState, type InfiniteRequestOptions, type InstanceApiContext, type InstanceApiResolvers, type InstancePluginExecutor, type LifecyclePhase, type MergePluginInstanceApi, type MergePluginOptions, type MergePluginResults, type MethodOptionsMap, type MiddlewareContext, type MiddlewareHandler, type MiddlewarePhase, type
|
|
1612
|
+
export { type AnyRequestOptions, type ApiSchema, type BuiltInEvents, type CacheEntry, type CacheEntryWithKey, type CapturedCall, type SpooshClientConfig as ClientConfig, type ComputeRequestOptions, type CoreRequestOptionsBase, type CreateInfiniteReadOptions, type CreateOperationOptions, type DataAwareCallback, type DataAwareTransform, type EventEmitter, type ExtractBody$1 as ExtractBody, type ExtractData, type ExtractError, type ExtractMethodOptions, type ExtractParamNames, type ExtractQuery$1 as ExtractQuery, type FetchDirection, type FetchExecutor, type FindMatchingKey, HTTP_METHODS, type HasParams, type HasReadMethod, type HasWriteMethod, type HeadersInitOrGetter, type HttpMethod, type HttpMethodKey, type InfiniteReadController, type InfiniteReadState, type InfiniteRequestOptions, type InstanceApiContext, type InstanceApiResolvers, type InstancePluginExecutor, type LifecyclePhase, type MergePluginInstanceApi, type MergePluginOptions, type MergePluginResults, type MethodOptionsMap, type MiddlewareContext, type MiddlewareHandler, type MiddlewarePhase, type OperationController, type OperationState, type OperationType, type PageContext, type PluginAccessor, type PluginArray, type PluginContext, type PluginContextInput, type PluginExecutor, type PluginExportsRegistry, type PluginFactory, type PluginHandler, type PluginLifecycle, type PluginMiddleware, type PluginRegistry, type PluginResolvers, type PluginResponseHandler, type PluginResultResolvers, type PluginTypeConfig, type PluginUpdateHandler, type ReadClient, type ReadPaths, type ReadSchemaHelper, type RefetchEvent, type RequestOptions$1 as RequestOptions, type ResolveInstanceApi, type ResolveResultTypes, type ResolveSchemaTypes, type ResolveTypes, type ResolverContext, type RetryConfig, type RouteToPath, type SchemaPaths, type SelectedEndpoint, type SelectorFunction, type SelectorResult, type Simplify, Spoosh, type SpooshBody, type SpooshClient, type SpooshConfig, type SpooshInstance, type SpooshMiddleware, type SpooshOptions, type SpooshOptionsExtra, type SpooshPlugin, type SpooshResponse, type SpooshSchema, type StateManager, type TagMode, type TagOptions, type WriteClient, type WriteMethod, type WritePaths, type WriteSchemaHelper, __DEV__, applyMiddlewares, buildUrl, composeMiddlewares, containsFile, createClient, createEventEmitter, createInfiniteReadController, createInitialState, createMiddleware, createOperationController, createPluginExecutor, createPluginRegistry, createProxyHandler, createSelectorProxy, createStateManager, executeFetch, extractMethodFromSelector, extractPathFromSelector, form, generateTags, getContentType, isJsonBody, isSpooshBody, json, mergeHeaders, objectToFormData, objectToUrlEncoded, resolveHeadersToRecord, resolvePath, resolveRequestBody, resolveTags, setHeaders, sortObjectKeys, urlencoded };
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
HTTP_METHODS: () => HTTP_METHODS,
|
|
24
24
|
Spoosh: () => Spoosh,
|
|
25
|
+
__DEV__: () => __DEV__,
|
|
25
26
|
applyMiddlewares: () => applyMiddlewares,
|
|
26
27
|
buildUrl: () => buildUrl,
|
|
27
28
|
composeMiddlewares: () => composeMiddlewares,
|
|
@@ -40,17 +41,22 @@ __export(src_exports, {
|
|
|
40
41
|
executeFetch: () => executeFetch,
|
|
41
42
|
extractMethodFromSelector: () => extractMethodFromSelector,
|
|
42
43
|
extractPathFromSelector: () => extractPathFromSelector,
|
|
44
|
+
form: () => form,
|
|
43
45
|
generateTags: () => generateTags,
|
|
44
46
|
getContentType: () => getContentType,
|
|
45
47
|
isJsonBody: () => isJsonBody,
|
|
48
|
+
isSpooshBody: () => isSpooshBody,
|
|
49
|
+
json: () => json,
|
|
46
50
|
mergeHeaders: () => mergeHeaders,
|
|
47
51
|
objectToFormData: () => objectToFormData,
|
|
48
52
|
objectToUrlEncoded: () => objectToUrlEncoded,
|
|
49
53
|
resolveHeadersToRecord: () => resolveHeadersToRecord,
|
|
50
54
|
resolvePath: () => resolvePath,
|
|
55
|
+
resolveRequestBody: () => resolveRequestBody,
|
|
51
56
|
resolveTags: () => resolveTags,
|
|
52
57
|
setHeaders: () => setHeaders,
|
|
53
|
-
sortObjectKeys: () => sortObjectKeys
|
|
58
|
+
sortObjectKeys: () => sortObjectKeys,
|
|
59
|
+
urlencoded: () => urlencoded
|
|
54
60
|
});
|
|
55
61
|
module.exports = __toCommonJS(src_exports);
|
|
56
62
|
|
|
@@ -99,6 +105,11 @@ function buildUrl(baseUrl, path, query) {
|
|
|
99
105
|
return `${cleanBase}${pathStr}${queryStr ? `?${queryStr}` : ""}`;
|
|
100
106
|
}
|
|
101
107
|
|
|
108
|
+
// src/utils/env.ts
|
|
109
|
+
function __DEV__() {
|
|
110
|
+
return typeof process !== "undefined" && true;
|
|
111
|
+
}
|
|
112
|
+
|
|
102
113
|
// src/utils/generateTags.ts
|
|
103
114
|
function generateTags(path) {
|
|
104
115
|
return path.map((_, i) => path.slice(0, i + 1).join("/"));
|
|
@@ -122,7 +133,6 @@ function isJsonBody(body) {
|
|
|
122
133
|
if (body instanceof ReadableStream) return false;
|
|
123
134
|
if (typeof body === "string") return false;
|
|
124
135
|
if (typeof body === "object") {
|
|
125
|
-
if (containsFile(body)) return false;
|
|
126
136
|
return true;
|
|
127
137
|
}
|
|
128
138
|
return false;
|
|
@@ -246,6 +256,67 @@ function sortObjectKeys(obj, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
246
256
|
);
|
|
247
257
|
}
|
|
248
258
|
|
|
259
|
+
// src/utils/body.ts
|
|
260
|
+
function isSpooshBody(value) {
|
|
261
|
+
return typeof value === "object" && value !== null && "__spooshBody" in value && value.__spooshBody === true;
|
|
262
|
+
}
|
|
263
|
+
function form(value) {
|
|
264
|
+
return Object.freeze({
|
|
265
|
+
__spooshBody: true,
|
|
266
|
+
kind: "form",
|
|
267
|
+
value
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function json(value) {
|
|
271
|
+
return Object.freeze({
|
|
272
|
+
__spooshBody: true,
|
|
273
|
+
kind: "json",
|
|
274
|
+
value
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
function urlencoded(value) {
|
|
278
|
+
return Object.freeze({
|
|
279
|
+
__spooshBody: true,
|
|
280
|
+
kind: "urlencoded",
|
|
281
|
+
value
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
function resolveRequestBody(rawBody) {
|
|
285
|
+
if (rawBody === void 0 || rawBody === null) {
|
|
286
|
+
return void 0;
|
|
287
|
+
}
|
|
288
|
+
if (isSpooshBody(rawBody)) {
|
|
289
|
+
switch (rawBody.kind) {
|
|
290
|
+
case "form":
|
|
291
|
+
return {
|
|
292
|
+
body: objectToFormData(rawBody.value)
|
|
293
|
+
};
|
|
294
|
+
case "json":
|
|
295
|
+
return {
|
|
296
|
+
body: JSON.stringify(rawBody.value),
|
|
297
|
+
headers: { "Content-Type": "application/json" }
|
|
298
|
+
};
|
|
299
|
+
case "urlencoded":
|
|
300
|
+
return {
|
|
301
|
+
body: objectToUrlEncoded(rawBody.value),
|
|
302
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" }
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (isJsonBody(rawBody)) {
|
|
307
|
+
if (__DEV__() && containsFile(rawBody)) {
|
|
308
|
+
console.warn(
|
|
309
|
+
"[spoosh] Plain object body contains File/Blob. Use form() wrapper for multipart upload."
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
body: JSON.stringify(rawBody),
|
|
314
|
+
headers: { "Content-Type": "application/json" }
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
return { body: rawBody };
|
|
318
|
+
}
|
|
319
|
+
|
|
249
320
|
// src/utils/path-utils.ts
|
|
250
321
|
function resolveTagMode(mode, path) {
|
|
251
322
|
switch (mode) {
|
|
@@ -391,25 +462,15 @@ async function executeCoreFetch(config) {
|
|
|
391
462
|
fetchInit.signal = requestOptions.signal;
|
|
392
463
|
}
|
|
393
464
|
if (requestOptions?.body !== void 0) {
|
|
394
|
-
const
|
|
395
|
-
if (
|
|
396
|
-
fetchInit.body =
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
);
|
|
403
|
-
} else if (isJsonBody(requestOptions.body)) {
|
|
404
|
-
fetchInit.body = JSON.stringify(requestOptions.body);
|
|
405
|
-
headers = await mergeHeaders(headers, {
|
|
406
|
-
"Content-Type": "application/json"
|
|
407
|
-
});
|
|
408
|
-
if (headers) {
|
|
409
|
-
fetchInit.headers = headers;
|
|
465
|
+
const resolved = resolveRequestBody(requestOptions.body);
|
|
466
|
+
if (resolved) {
|
|
467
|
+
fetchInit.body = resolved.body;
|
|
468
|
+
if (resolved.headers) {
|
|
469
|
+
headers = await mergeHeaders(headers, resolved.headers);
|
|
470
|
+
if (headers) {
|
|
471
|
+
fetchInit.headers = headers;
|
|
472
|
+
}
|
|
410
473
|
}
|
|
411
|
-
} else {
|
|
412
|
-
fetchInit.body = requestOptions.body;
|
|
413
474
|
}
|
|
414
475
|
}
|
|
415
476
|
let lastError;
|
package/dist/index.mjs
CHANGED
|
@@ -43,6 +43,11 @@ function buildUrl(baseUrl, path, query) {
|
|
|
43
43
|
return `${cleanBase}${pathStr}${queryStr ? `?${queryStr}` : ""}`;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// src/utils/env.ts
|
|
47
|
+
function __DEV__() {
|
|
48
|
+
return typeof process !== "undefined" && true;
|
|
49
|
+
}
|
|
50
|
+
|
|
46
51
|
// src/utils/generateTags.ts
|
|
47
52
|
function generateTags(path) {
|
|
48
53
|
return path.map((_, i) => path.slice(0, i + 1).join("/"));
|
|
@@ -66,7 +71,6 @@ function isJsonBody(body) {
|
|
|
66
71
|
if (body instanceof ReadableStream) return false;
|
|
67
72
|
if (typeof body === "string") return false;
|
|
68
73
|
if (typeof body === "object") {
|
|
69
|
-
if (containsFile(body)) return false;
|
|
70
74
|
return true;
|
|
71
75
|
}
|
|
72
76
|
return false;
|
|
@@ -190,6 +194,67 @@ function sortObjectKeys(obj, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
190
194
|
);
|
|
191
195
|
}
|
|
192
196
|
|
|
197
|
+
// src/utils/body.ts
|
|
198
|
+
function isSpooshBody(value) {
|
|
199
|
+
return typeof value === "object" && value !== null && "__spooshBody" in value && value.__spooshBody === true;
|
|
200
|
+
}
|
|
201
|
+
function form(value) {
|
|
202
|
+
return Object.freeze({
|
|
203
|
+
__spooshBody: true,
|
|
204
|
+
kind: "form",
|
|
205
|
+
value
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function json(value) {
|
|
209
|
+
return Object.freeze({
|
|
210
|
+
__spooshBody: true,
|
|
211
|
+
kind: "json",
|
|
212
|
+
value
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function urlencoded(value) {
|
|
216
|
+
return Object.freeze({
|
|
217
|
+
__spooshBody: true,
|
|
218
|
+
kind: "urlencoded",
|
|
219
|
+
value
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
function resolveRequestBody(rawBody) {
|
|
223
|
+
if (rawBody === void 0 || rawBody === null) {
|
|
224
|
+
return void 0;
|
|
225
|
+
}
|
|
226
|
+
if (isSpooshBody(rawBody)) {
|
|
227
|
+
switch (rawBody.kind) {
|
|
228
|
+
case "form":
|
|
229
|
+
return {
|
|
230
|
+
body: objectToFormData(rawBody.value)
|
|
231
|
+
};
|
|
232
|
+
case "json":
|
|
233
|
+
return {
|
|
234
|
+
body: JSON.stringify(rawBody.value),
|
|
235
|
+
headers: { "Content-Type": "application/json" }
|
|
236
|
+
};
|
|
237
|
+
case "urlencoded":
|
|
238
|
+
return {
|
|
239
|
+
body: objectToUrlEncoded(rawBody.value),
|
|
240
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" }
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (isJsonBody(rawBody)) {
|
|
245
|
+
if (__DEV__() && containsFile(rawBody)) {
|
|
246
|
+
console.warn(
|
|
247
|
+
"[spoosh] Plain object body contains File/Blob. Use form() wrapper for multipart upload."
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
body: JSON.stringify(rawBody),
|
|
252
|
+
headers: { "Content-Type": "application/json" }
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
return { body: rawBody };
|
|
256
|
+
}
|
|
257
|
+
|
|
193
258
|
// src/utils/path-utils.ts
|
|
194
259
|
function resolveTagMode(mode, path) {
|
|
195
260
|
switch (mode) {
|
|
@@ -335,25 +400,15 @@ async function executeCoreFetch(config) {
|
|
|
335
400
|
fetchInit.signal = requestOptions.signal;
|
|
336
401
|
}
|
|
337
402
|
if (requestOptions?.body !== void 0) {
|
|
338
|
-
const
|
|
339
|
-
if (
|
|
340
|
-
fetchInit.body =
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
);
|
|
347
|
-
} else if (isJsonBody(requestOptions.body)) {
|
|
348
|
-
fetchInit.body = JSON.stringify(requestOptions.body);
|
|
349
|
-
headers = await mergeHeaders(headers, {
|
|
350
|
-
"Content-Type": "application/json"
|
|
351
|
-
});
|
|
352
|
-
if (headers) {
|
|
353
|
-
fetchInit.headers = headers;
|
|
403
|
+
const resolved = resolveRequestBody(requestOptions.body);
|
|
404
|
+
if (resolved) {
|
|
405
|
+
fetchInit.body = resolved.body;
|
|
406
|
+
if (resolved.headers) {
|
|
407
|
+
headers = await mergeHeaders(headers, resolved.headers);
|
|
408
|
+
if (headers) {
|
|
409
|
+
fetchInit.headers = headers;
|
|
410
|
+
}
|
|
354
411
|
}
|
|
355
|
-
} else {
|
|
356
|
-
fetchInit.body = requestOptions.body;
|
|
357
412
|
}
|
|
358
413
|
}
|
|
359
414
|
let lastError;
|
|
@@ -1607,6 +1662,7 @@ function createInfiniteReadController(options) {
|
|
|
1607
1662
|
export {
|
|
1608
1663
|
HTTP_METHODS,
|
|
1609
1664
|
Spoosh,
|
|
1665
|
+
__DEV__,
|
|
1610
1666
|
applyMiddlewares,
|
|
1611
1667
|
buildUrl,
|
|
1612
1668
|
composeMiddlewares,
|
|
@@ -1625,15 +1681,20 @@ export {
|
|
|
1625
1681
|
executeFetch,
|
|
1626
1682
|
extractMethodFromSelector,
|
|
1627
1683
|
extractPathFromSelector,
|
|
1684
|
+
form,
|
|
1628
1685
|
generateTags,
|
|
1629
1686
|
getContentType,
|
|
1630
1687
|
isJsonBody,
|
|
1688
|
+
isSpooshBody,
|
|
1689
|
+
json,
|
|
1631
1690
|
mergeHeaders,
|
|
1632
1691
|
objectToFormData,
|
|
1633
1692
|
objectToUrlEncoded,
|
|
1634
1693
|
resolveHeadersToRecord,
|
|
1635
1694
|
resolvePath,
|
|
1695
|
+
resolveRequestBody,
|
|
1636
1696
|
resolveTags,
|
|
1637
1697
|
setHeaders,
|
|
1638
|
-
sortObjectKeys
|
|
1698
|
+
sortObjectKeys,
|
|
1699
|
+
urlencoded
|
|
1639
1700
|
};
|