@spoosh/core 0.4.3 → 0.6.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 +41 -47
- package/dist/index.d.mts +389 -255
- package/dist/index.d.ts +389 -255
- package/dist/index.js +90 -114
- package/dist/index.mjs +90 -114
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
2
|
-
type SchemaMethod = "$get" | "$post" | "$put" | "$patch" | "$delete";
|
|
3
2
|
|
|
4
3
|
type MiddlewarePhase = "before" | "after";
|
|
5
4
|
type MiddlewareContext<TData = unknown, TError = unknown> = {
|
|
@@ -71,41 +70,27 @@ type HeadersInitOrGetter = HeadersInit | (() => HeadersInit | Promise<HeadersIni
|
|
|
71
70
|
type SpooshOptions = Omit<RequestInit, "method" | "body" | "headers"> & {
|
|
72
71
|
headers?: HeadersInitOrGetter;
|
|
73
72
|
};
|
|
74
|
-
type BaseRequestOptions = {
|
|
73
|
+
type BaseRequestOptions$1 = {
|
|
75
74
|
headers?: HeadersInitOrGetter;
|
|
76
75
|
cache?: RequestCache;
|
|
77
76
|
signal?: AbortSignal;
|
|
78
77
|
};
|
|
79
|
-
type BodyOption<TBody> = [TBody] extends [never] ? object : undefined extends TBody ? {
|
|
78
|
+
type BodyOption$1<TBody> = [TBody] extends [never] ? object : undefined extends TBody ? {
|
|
80
79
|
body?: Exclude<TBody, undefined>;
|
|
81
80
|
} : {
|
|
82
81
|
body: TBody;
|
|
83
82
|
};
|
|
84
|
-
type QueryOption<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
|
|
83
|
+
type QueryOption$1<TQuery> = [TQuery] extends [never] ? object : undefined extends TQuery ? {
|
|
85
84
|
query?: Exclude<TQuery, undefined>;
|
|
86
85
|
} : {
|
|
87
86
|
query: TQuery;
|
|
88
87
|
};
|
|
89
|
-
type
|
|
90
|
-
|
|
91
|
-
} : {
|
|
92
|
-
formData: TFormData;
|
|
93
|
-
};
|
|
94
|
-
type UrlEncodedOption<TUrlEncoded> = [TUrlEncoded] extends [never] ? object : undefined extends TUrlEncoded ? {
|
|
95
|
-
urlEncoded?: Exclude<TUrlEncoded, undefined>;
|
|
96
|
-
} : {
|
|
97
|
-
urlEncoded: TUrlEncoded;
|
|
98
|
-
};
|
|
99
|
-
type RequestOptions<TBody = never, TQuery = never, TFormData = never, TUrlEncoded = never> = BaseRequestOptions & BodyOption<TBody> & QueryOption<TQuery> & FormDataOption<TFormData> & UrlEncodedOption<TUrlEncoded>;
|
|
100
|
-
type AnyRequestOptions = BaseRequestOptions & {
|
|
88
|
+
type RequestOptions$1<TBody = never, TQuery = never> = BaseRequestOptions$1 & BodyOption$1<TBody> & QueryOption$1<TQuery>;
|
|
89
|
+
type AnyRequestOptions = BaseRequestOptions$1 & {
|
|
101
90
|
body?: unknown;
|
|
102
91
|
query?: Record<string, string | number | boolean | undefined>;
|
|
103
|
-
formData?: Record<string, unknown>;
|
|
104
|
-
urlEncoded?: Record<string, unknown>;
|
|
105
92
|
params?: Record<string, string | number>;
|
|
106
93
|
signal?: AbortSignal;
|
|
107
|
-
/** @internal Path transformer function. Set by plugins like path-case. */
|
|
108
|
-
_pathTransformer?: (path: string[]) => string[];
|
|
109
94
|
} & Partial<RetryConfig>;
|
|
110
95
|
type DynamicParamsOption = {
|
|
111
96
|
params?: Record<string, string | number>;
|
|
@@ -114,13 +99,13 @@ type CoreRequestOptionsBase = {
|
|
|
114
99
|
__hasDynamicParams?: DynamicParamsOption;
|
|
115
100
|
};
|
|
116
101
|
type MethodOptionsMap<TQueryOptions = object, TMutationOptions = object> = {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
102
|
+
GET: TQueryOptions;
|
|
103
|
+
POST: TMutationOptions;
|
|
104
|
+
PUT: TMutationOptions;
|
|
105
|
+
PATCH: TMutationOptions;
|
|
106
|
+
DELETE: TMutationOptions;
|
|
122
107
|
};
|
|
123
|
-
type ExtractMethodOptions<TOptionsMap, TMethod extends
|
|
108
|
+
type ExtractMethodOptions<TOptionsMap, TMethod extends HttpMethod> = TOptionsMap extends MethodOptionsMap<infer TQuery, infer TMutation> ? TMethod extends "GET" ? TQuery : TMutation : TOptionsMap;
|
|
124
109
|
type FetchExecutor<TOptions = SpooshOptions, TRequestOptions = AnyRequestOptions> = <TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: TOptions, requestOptions?: TRequestOptions, nextTags?: boolean) => Promise<SpooshResponse<TData, TError>>;
|
|
125
110
|
type TypedParamsOption<TParamNames extends string> = [TParamNames] extends [
|
|
126
111
|
never
|
|
@@ -205,7 +190,7 @@ type StateManager = {
|
|
|
205
190
|
getCacheByTags: <TData>(tags: string[]) => CacheEntry<TData> | undefined;
|
|
206
191
|
getCacheEntriesByTags: <TData, TError>(tags: string[]) => CacheEntryWithKey<TData, TError>[];
|
|
207
192
|
getCacheEntriesBySelfTag: <TData, TError>(selfTag: string) => CacheEntryWithKey<TData, TError>[];
|
|
208
|
-
|
|
193
|
+
setMeta: (key: string, data: Record<string, unknown>) => void;
|
|
209
194
|
/** Mark all cache entries with matching tags as stale */
|
|
210
195
|
markStale: (tags: string[]) => void;
|
|
211
196
|
/** Get all cache entries */
|
|
@@ -231,7 +216,7 @@ type CacheEntry<TData = unknown, TError = unknown> = {
|
|
|
231
216
|
state: OperationState<TData, TError>;
|
|
232
217
|
tags: string[];
|
|
233
218
|
/** Plugin-contributed result data (e.g., isOptimistic, isStale). Merged into hook result. */
|
|
234
|
-
|
|
219
|
+
meta: Map<string, unknown>;
|
|
235
220
|
/** The original path-derived tag (e.g., "posts/1/comments"). Used for exact matching in cache */
|
|
236
221
|
selfTag?: string;
|
|
237
222
|
previousData?: TData;
|
|
@@ -448,7 +433,7 @@ type DataAwareTransform<TData = unknown, TError = unknown> = (data: TData | unde
|
|
|
448
433
|
* Context object containing all type information available for resolution.
|
|
449
434
|
* 3rd party plugins can access any combination of these types.
|
|
450
435
|
*/
|
|
451
|
-
type ResolverContext<TSchema = unknown, TData = unknown, TError = unknown, TQuery = unknown, TBody = unknown, TParams = unknown
|
|
436
|
+
type ResolverContext<TSchema = unknown, TData = unknown, TError = unknown, TQuery = unknown, TBody = unknown, TParams = unknown> = {
|
|
452
437
|
schema: TSchema;
|
|
453
438
|
data: TData;
|
|
454
439
|
error: TError;
|
|
@@ -456,8 +441,6 @@ type ResolverContext<TSchema = unknown, TData = unknown, TError = unknown, TQuer
|
|
|
456
441
|
query: TQuery;
|
|
457
442
|
body: TBody;
|
|
458
443
|
params: TParams;
|
|
459
|
-
formData: TFormData;
|
|
460
|
-
urlEncoded: TUrlEncoded;
|
|
461
444
|
};
|
|
462
445
|
};
|
|
463
446
|
/**
|
|
@@ -704,175 +687,166 @@ type PluginRegistry<TPlugins extends SpooshPlugin<PluginTypeConfig>[]> = {
|
|
|
704
687
|
};
|
|
705
688
|
declare function createPluginRegistry<TPlugins extends SpooshPlugin<PluginTypeConfig>[]>(plugins: [...TPlugins]): PluginRegistry<TPlugins>;
|
|
706
689
|
|
|
707
|
-
declare const EndpointBrand: unique symbol;
|
|
708
690
|
/**
|
|
709
|
-
*
|
|
691
|
+
* An API schema where routes are defined as string keys with path patterns.
|
|
692
|
+
* Define data, body, query, and error directly on each method.
|
|
710
693
|
*
|
|
711
694
|
* @example
|
|
712
|
-
* ```
|
|
713
|
-
*
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
*
|
|
719
|
-
*
|
|
720
|
-
*
|
|
721
|
-
*
|
|
722
|
-
*
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
*
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
* // With error type
|
|
729
|
-
* $get: Endpoint<{ data: User; error: ApiError }>
|
|
730
|
-
*
|
|
731
|
-
* // Complex: query + body + error
|
|
732
|
-
* $post: Endpoint<{ data: User; body: CreateUserBody; query: { notify?: boolean }; error: ApiError }>
|
|
695
|
+
* ```ts
|
|
696
|
+
* type ApiSchema = {
|
|
697
|
+
* "posts": {
|
|
698
|
+
* GET: { data: Post[] };
|
|
699
|
+
* POST: { data: Post; body: CreatePostBody };
|
|
700
|
+
* };
|
|
701
|
+
* "posts/:id": {
|
|
702
|
+
* GET: { data: Post };
|
|
703
|
+
* PUT: { data: Post; body: UpdatePostBody };
|
|
704
|
+
* DELETE: { data: void };
|
|
705
|
+
* };
|
|
706
|
+
* "posts/:id/comments": {
|
|
707
|
+
* GET: { data: Comment[]; query: { page?: number } };
|
|
708
|
+
* };
|
|
709
|
+
* };
|
|
733
710
|
* ```
|
|
734
711
|
*/
|
|
735
|
-
type
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
} & T;
|
|
745
|
-
type ExtractProperty<T, K extends string, TDefault = never> = K extends keyof T ? T[K] : TDefault;
|
|
746
|
-
type NormalizeEndpoint<T, TDefaultError> = T extends {
|
|
747
|
-
[EndpointBrand]: true;
|
|
748
|
-
} ? {
|
|
749
|
-
data: ExtractProperty<T, "data">;
|
|
750
|
-
error: ExtractProperty<T, "error", TDefaultError>;
|
|
751
|
-
body: ExtractProperty<T, "body">;
|
|
752
|
-
query: ExtractProperty<T, "query">;
|
|
753
|
-
formData: ExtractProperty<T, "formData">;
|
|
754
|
-
urlEncoded: ExtractProperty<T, "urlEncoded">;
|
|
755
|
-
} : {
|
|
756
|
-
data: T;
|
|
757
|
-
error: TDefaultError;
|
|
758
|
-
body: never;
|
|
759
|
-
query: never;
|
|
760
|
-
formData: never;
|
|
761
|
-
urlEncoded: never;
|
|
712
|
+
type ApiSchema = {
|
|
713
|
+
[path: string]: {
|
|
714
|
+
[method in HttpMethod]?: {
|
|
715
|
+
data: unknown;
|
|
716
|
+
body?: unknown;
|
|
717
|
+
query?: unknown;
|
|
718
|
+
error?: unknown;
|
|
719
|
+
};
|
|
720
|
+
};
|
|
762
721
|
};
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
type ExtractData<
|
|
722
|
+
/**
|
|
723
|
+
* Extract data type from an endpoint.
|
|
724
|
+
*/
|
|
725
|
+
type ExtractData<T> = T extends {
|
|
767
726
|
data: infer D;
|
|
768
727
|
} ? D : never;
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
type ExtractBody<
|
|
728
|
+
/**
|
|
729
|
+
* Extract body type from an endpoint.
|
|
730
|
+
*/
|
|
731
|
+
type ExtractBody$1<T> = T extends {
|
|
773
732
|
body: infer B;
|
|
774
733
|
} ? B : never;
|
|
775
|
-
|
|
734
|
+
/**
|
|
735
|
+
* Extract query type from an endpoint.
|
|
736
|
+
*/
|
|
737
|
+
type ExtractQuery$1<T> = T extends {
|
|
776
738
|
query: infer Q;
|
|
777
739
|
} ? Q : never;
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
type
|
|
782
|
-
|
|
783
|
-
} ?
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
type
|
|
823
|
-
type
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
} ?
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
type
|
|
839
|
-
[K in
|
|
840
|
-
};
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
740
|
+
/**
|
|
741
|
+
* Extract error type from an endpoint.
|
|
742
|
+
*/
|
|
743
|
+
type ExtractError<T, TDefault = unknown> = T extends {
|
|
744
|
+
error: infer E;
|
|
745
|
+
} ? E : TDefault;
|
|
746
|
+
/**
|
|
747
|
+
* Helper type to define a type-safe API schema.
|
|
748
|
+
* Use this to get type checking on your schema definition.
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* ```ts
|
|
752
|
+
* type ApiSchema = SpooshSchema<{
|
|
753
|
+
* "posts": {
|
|
754
|
+
* GET: { data: Post[] };
|
|
755
|
+
* POST: { data: Post; body: CreatePostBody };
|
|
756
|
+
* };
|
|
757
|
+
* "posts/:id": {
|
|
758
|
+
* GET: { data: Post };
|
|
759
|
+
* PUT: { data: Post; body: UpdatePostBody };
|
|
760
|
+
* DELETE: { data: void };
|
|
761
|
+
* };
|
|
762
|
+
* }>;
|
|
763
|
+
*
|
|
764
|
+
* const api = createClient<ApiSchema>({ baseUrl: "/api" });
|
|
765
|
+
* ```
|
|
766
|
+
*/
|
|
767
|
+
type SpooshSchema<T extends {
|
|
768
|
+
[path: string]: {
|
|
769
|
+
[M in HttpMethod]?: {
|
|
770
|
+
data: unknown;
|
|
771
|
+
body?: unknown;
|
|
772
|
+
query?: unknown;
|
|
773
|
+
error?: unknown;
|
|
774
|
+
};
|
|
775
|
+
};
|
|
776
|
+
}> = T;
|
|
777
|
+
/**
|
|
778
|
+
* Convert a route pattern like "posts/:id" to a path matcher pattern like `posts/${string}`.
|
|
779
|
+
* This enables TypeScript to match actual paths like "posts/123" to their schema definitions.
|
|
780
|
+
*
|
|
781
|
+
* @example
|
|
782
|
+
* ```ts
|
|
783
|
+
* type A = RouteToPath<"posts/:id">; // "posts/${string}"
|
|
784
|
+
* type B = RouteToPath<"posts/:id/comments/:cid">; // "posts/${string}/comments/${string}"
|
|
785
|
+
* type C = RouteToPath<"posts">; // "posts"
|
|
786
|
+
* ```
|
|
787
|
+
*/
|
|
788
|
+
type RouteToPath<T extends string> = T extends `${infer Start}/:${string}/${infer Rest}` ? `${Start}/${string}/${RouteToPath<Rest>}` : T extends `${infer Start}/:${string}` ? `${Start}/${string}` : T;
|
|
789
|
+
/**
|
|
790
|
+
* Find which schema key matches a given path.
|
|
791
|
+
* First checks for exact match, then checks pattern matches.
|
|
792
|
+
*
|
|
793
|
+
* @example
|
|
794
|
+
* ```ts
|
|
795
|
+
* type Schema = { "posts": {...}; "posts/:id": {...} };
|
|
796
|
+
* type A = FindMatchingKey<Schema, "posts">; // "posts" (exact match)
|
|
797
|
+
* type B = FindMatchingKey<Schema, "posts/123">; // "posts/:id" (pattern match)
|
|
798
|
+
* ```
|
|
799
|
+
*/
|
|
800
|
+
type FindMatchingKey<TSchema, TPath extends string> = TPath extends keyof TSchema ? TPath : {
|
|
801
|
+
[K in keyof TSchema]: TPath extends RouteToPath<K & string> ? K : never;
|
|
802
|
+
}[keyof TSchema];
|
|
803
|
+
/**
|
|
804
|
+
* Extract parameter names from a route pattern.
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* ```ts
|
|
808
|
+
* type A = ExtractParamNames<"posts/:id">; // "id"
|
|
809
|
+
* type B = ExtractParamNames<"posts/:id/comments/:cid">; // "id" | "cid"
|
|
810
|
+
* type C = ExtractParamNames<"posts">; // never
|
|
811
|
+
* ```
|
|
812
|
+
*/
|
|
813
|
+
type ExtractParamNames<T extends string> = T extends `${string}:${infer Param}/${infer Rest}` ? Param | ExtractParamNames<Rest> : T extends `${string}:${infer Param}` ? Param : never;
|
|
814
|
+
/**
|
|
815
|
+
* Check if a route pattern has any parameters.
|
|
816
|
+
*
|
|
817
|
+
* @example
|
|
818
|
+
* ```ts
|
|
819
|
+
* type A = HasParams<"posts/:id">; // true
|
|
820
|
+
* type B = HasParams<"posts">; // false
|
|
821
|
+
* ```
|
|
822
|
+
*/
|
|
823
|
+
type HasParams<T extends string> = T extends `${string}:${string}` ? true : false;
|
|
861
824
|
|
|
862
|
-
type
|
|
863
|
-
|
|
864
|
-
}
|
|
865
|
-
type
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
825
|
+
type Simplify$1<T> = {
|
|
826
|
+
[K in keyof T]: T[K];
|
|
827
|
+
} & {};
|
|
828
|
+
type IsNever<T> = [T] extends [never] ? true : false;
|
|
829
|
+
type EndpointRequestOptions<TEndpoint, TPath extends string> = (IsNever<ExtractBody$1<TEndpoint>> extends true ? object : {
|
|
830
|
+
body: ExtractBody$1<TEndpoint>;
|
|
831
|
+
}) & (IsNever<ExtractQuery$1<TEndpoint>> extends true ? object : {
|
|
832
|
+
query: ExtractQuery$1<TEndpoint>;
|
|
833
|
+
}) & (HasParams<TPath> extends true ? {
|
|
834
|
+
params: Record<ExtractParamNames<TPath>, string | number>;
|
|
835
|
+
} : object);
|
|
836
|
+
type EndpointMethodFn<TEndpoint, TPath extends string> = (options?: Simplify$1<EndpointRequestOptions<TEndpoint, TPath>>) => Promise<SpooshResponse<ExtractData<TEndpoint>, unknown, EndpointRequestOptions<TEndpoint, TPath>>>;
|
|
837
|
+
type QueryPathMethods<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? Simplify$1<{
|
|
838
|
+
GET: EndpointMethodFn<TSchema[TKey]["GET"], TPath>;
|
|
839
|
+
}> : never : never : never;
|
|
840
|
+
type ReadPaths$1<TSchema> = {
|
|
841
|
+
[K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
|
|
842
|
+
}[keyof TSchema & string];
|
|
843
|
+
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;
|
|
869
844
|
/**
|
|
870
845
|
* Schema navigation helper for plugins that need type-safe API schema access.
|
|
871
846
|
*
|
|
872
|
-
* This type transforms the API schema into a
|
|
873
|
-
* -
|
|
874
|
-
* -
|
|
875
|
-
* - `$get` endpoints become callable method types
|
|
847
|
+
* This type transforms the API schema into a callable function where:
|
|
848
|
+
* - Path strings are used to select endpoints
|
|
849
|
+
* - Only GET methods are exposed (for query operations)
|
|
876
850
|
*
|
|
877
851
|
* Use this in plugin option types that need to reference API endpoints:
|
|
878
852
|
*
|
|
@@ -901,22 +875,182 @@ type EndpointToMethod<T> = (options?: ExtractEndpointRequestOptions<T>) => Promi
|
|
|
901
875
|
* // User's code - paths are type-checked!
|
|
902
876
|
* trigger({
|
|
903
877
|
* myCallback: (api) => [
|
|
904
|
-
* api.
|
|
905
|
-
* api
|
|
906
|
-
* api.
|
|
878
|
+
* api("posts").GET, // ✓ Valid
|
|
879
|
+
* api("posts/:id").GET, // ✓ Dynamic segment
|
|
880
|
+
* api("nonexistent").GET, // ✗ Type error
|
|
907
881
|
* ],
|
|
908
882
|
* });
|
|
909
883
|
* ```
|
|
910
884
|
*/
|
|
911
|
-
type QuerySchemaHelper<TSchema> = {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
[
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
885
|
+
type QuerySchemaHelper<TSchema> = <TPath extends ReadPaths$1<TSchema> | (string & {})>(path: TPath) => HasGetMethod$1<TSchema, TPath> extends true ? QueryPathMethods<TSchema, TPath> : never;
|
|
886
|
+
type MutationMethod$1 = "POST" | "PUT" | "PATCH" | "DELETE";
|
|
887
|
+
type MutationPathMethods<TSchema, TPath extends string> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? Simplify$1<{
|
|
888
|
+
[M in MutationMethod$1 as M extends keyof TSchema[TKey] ? M : never]: M extends keyof TSchema[TKey] ? EndpointMethodFn<TSchema[TKey][M], TPath> : never;
|
|
889
|
+
}> : never : never;
|
|
890
|
+
type WritePaths$1<TSchema> = {
|
|
891
|
+
[K in keyof TSchema & string]: Extract<keyof TSchema[K], MutationMethod$1> extends never ? never : K;
|
|
892
|
+
}[keyof TSchema & string];
|
|
893
|
+
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;
|
|
894
|
+
/**
|
|
895
|
+
* Schema navigation helper for plugins that need type-safe API schema access for mutations.
|
|
896
|
+
*
|
|
897
|
+
* Similar to QuerySchemaHelper but exposes mutation methods (POST, PUT, PATCH, DELETE).
|
|
898
|
+
*/
|
|
899
|
+
type MutationSchemaHelper<TSchema> = <TPath extends WritePaths$1<TSchema> | (string & {})>(path: TPath) => HasMutationMethod$1<TSchema, TPath> extends true ? MutationPathMethods<TSchema, TPath> : never;
|
|
900
|
+
|
|
901
|
+
type Simplify<T> = {
|
|
902
|
+
[K in keyof T]: T[K];
|
|
903
|
+
} & {};
|
|
904
|
+
/**
|
|
905
|
+
* Base request options available on all methods.
|
|
906
|
+
*/
|
|
907
|
+
type BaseRequestOptions = {
|
|
908
|
+
headers?: HeadersInitOrGetter;
|
|
909
|
+
cache?: RequestCache;
|
|
910
|
+
signal?: AbortSignal;
|
|
911
|
+
};
|
|
912
|
+
/**
|
|
913
|
+
* Extract body type from method config.
|
|
914
|
+
*/
|
|
915
|
+
type ExtractBody<T> = T extends {
|
|
916
|
+
body?: infer B;
|
|
917
|
+
} ? B : never;
|
|
918
|
+
/**
|
|
919
|
+
* Extract query type from method config.
|
|
920
|
+
*/
|
|
921
|
+
type ExtractQuery<T> = T extends {
|
|
922
|
+
query?: infer Q;
|
|
923
|
+
} ? Q : never;
|
|
924
|
+
/**
|
|
925
|
+
* Check if body is required (not optional).
|
|
926
|
+
*/
|
|
927
|
+
type IsBodyRequired<T> = T extends {
|
|
928
|
+
body: infer B;
|
|
929
|
+
} ? undefined extends B ? false : true : false;
|
|
930
|
+
/**
|
|
931
|
+
* Check if query is required (not optional).
|
|
932
|
+
*/
|
|
933
|
+
type IsQueryRequired<T> = T extends {
|
|
934
|
+
query: infer Q;
|
|
935
|
+
} ? undefined extends Q ? false : true : false;
|
|
936
|
+
/**
|
|
937
|
+
* Build the options type for a method.
|
|
938
|
+
*/
|
|
939
|
+
type BodyOption<T> = [ExtractBody<T>] extends [never] ? {} : IsBodyRequired<T> extends true ? {
|
|
940
|
+
body: ExtractBody<T>;
|
|
941
|
+
} : {
|
|
942
|
+
body?: ExtractBody<T>;
|
|
943
|
+
};
|
|
944
|
+
type QueryOption<T> = [ExtractQuery<T>] extends [never] ? {} : IsQueryRequired<T> extends true ? {
|
|
945
|
+
query: ExtractQuery<T>;
|
|
946
|
+
} : {
|
|
947
|
+
query?: ExtractQuery<T>;
|
|
948
|
+
};
|
|
949
|
+
type ParamsOption<TUserPath extends string> = HasParams<TUserPath> extends true ? {
|
|
950
|
+
params: Record<ExtractParamNames<TUserPath>, string | number>;
|
|
951
|
+
} : {};
|
|
952
|
+
type RequestOptions<TMethodConfig, TUserPath extends string> = Simplify<BaseRequestOptions & BodyOption<TMethodConfig> & QueryOption<TMethodConfig> & ParamsOption<TUserPath>>;
|
|
953
|
+
/**
|
|
954
|
+
* Check if options argument is required.
|
|
955
|
+
*/
|
|
956
|
+
type IsOptionsRequired<TMethodConfig, TUserPath extends string> = IsBodyRequired<TMethodConfig> extends true ? true : IsQueryRequired<TMethodConfig> extends true ? true : HasParams<TUserPath> extends true ? true : false;
|
|
957
|
+
/**
|
|
958
|
+
* Build response type for a method call.
|
|
959
|
+
*/
|
|
960
|
+
type MethodResponse<TMethodConfig, TDefaultError, TUserPath extends string> = SpooshResponse<ExtractData<TMethodConfig>, ExtractError<TMethodConfig, TDefaultError>, RequestOptions<TMethodConfig, TUserPath>, ExtractQuery<TMethodConfig>, ExtractBody<TMethodConfig>, never, never, ExtractParamNames<TUserPath>>;
|
|
961
|
+
/**
|
|
962
|
+
* Create a method function type.
|
|
963
|
+
* Direct lookup: Schema[Path][Method] → method config → build function type
|
|
964
|
+
*/
|
|
965
|
+
type MethodFn<TMethodConfig, TDefaultError, TUserPath extends string> = IsOptionsRequired<TMethodConfig, TUserPath> extends true ? (options: RequestOptions<TMethodConfig, TUserPath>) => Promise<MethodResponse<TMethodConfig, TDefaultError, TUserPath>> : (options?: RequestOptions<TMethodConfig, TUserPath>) => Promise<MethodResponse<TMethodConfig, TDefaultError, TUserPath>>;
|
|
966
|
+
/**
|
|
967
|
+
* HTTP methods available on a path.
|
|
968
|
+
* Direct lookup: Schema[Path] → route config → map methods
|
|
969
|
+
*/
|
|
970
|
+
type HttpMethods<TRoute, TDefaultError, TUserPath extends string> = {
|
|
971
|
+
[M in HttpMethod as M extends keyof TRoute ? M : never]: M extends keyof TRoute ? MethodFn<TRoute[M], TDefaultError, TUserPath> : never;
|
|
972
|
+
};
|
|
973
|
+
/**
|
|
974
|
+
* Build the return type when calling a client with a path.
|
|
975
|
+
* Uses FindMatchingKey for pattern matching (e.g., "posts/123" → "posts/:id")
|
|
976
|
+
*/
|
|
977
|
+
type PathMethods<TSchema, TPath extends string, TDefaultError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? Simplify<HttpMethods<TSchema[TKey], TDefaultError, TPath>> : never : never;
|
|
978
|
+
/**
|
|
979
|
+
* Extract all valid paths from a schema (for autocomplete).
|
|
980
|
+
*/
|
|
981
|
+
type SchemaPaths<TSchema> = keyof TSchema & string;
|
|
982
|
+
/**
|
|
983
|
+
* An API client that uses path strings instead of chained property access.
|
|
984
|
+
* Methods use HTTP names directly: GET, POST, PUT, PATCH, DELETE.
|
|
985
|
+
*
|
|
986
|
+
* @example
|
|
987
|
+
* ```ts
|
|
988
|
+
* type ApiSchema = {
|
|
989
|
+
* "posts": { GET: { data: Post[] } };
|
|
990
|
+
* "posts/:id": { GET: { data: Post } };
|
|
991
|
+
* };
|
|
992
|
+
*
|
|
993
|
+
* const api = createClient<ApiSchema>({ baseUrl: "/api" });
|
|
994
|
+
*
|
|
995
|
+
* // Call with exact path (autocomplete available)
|
|
996
|
+
* await api("posts").GET();
|
|
997
|
+
*
|
|
998
|
+
* // Call with embedded params (matches "posts/:id")
|
|
999
|
+
* await api("posts/123").GET();
|
|
1000
|
+
*
|
|
1001
|
+
* // Call with explicit params
|
|
1002
|
+
* await api("posts/:id").GET({ params: { id: 123 } });
|
|
1003
|
+
* ```
|
|
1004
|
+
*/
|
|
1005
|
+
type SpooshClient<TSchema, TDefaultError = unknown> = <TPath extends SchemaPaths<TSchema> | (string & {})>(path: TPath) => PathMethods<TSchema, TPath, TDefaultError>;
|
|
1006
|
+
/**
|
|
1007
|
+
* Read-only client type that only exposes GET methods.
|
|
1008
|
+
* Used by useRead/injectRead hooks to ensure only query operations are selected.
|
|
1009
|
+
*/
|
|
1010
|
+
type ReadPathMethods<TSchema, TPath extends string, TDefaultError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? "GET" extends keyof TSchema[TKey] ? Simplify<{
|
|
1011
|
+
GET: MethodFn<TSchema[TKey]["GET"], TDefaultError, TPath>;
|
|
1012
|
+
}> : never : never : never;
|
|
1013
|
+
/**
|
|
1014
|
+
* Check if a schema path has a GET method.
|
|
1015
|
+
*/
|
|
1016
|
+
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;
|
|
1017
|
+
/**
|
|
1018
|
+
* Extract paths that have GET methods.
|
|
1019
|
+
*/
|
|
1020
|
+
type ReadPaths<TSchema> = {
|
|
1021
|
+
[K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
|
|
1022
|
+
}[keyof TSchema & string];
|
|
1023
|
+
/**
|
|
1024
|
+
* A read-only API client that only exposes GET methods.
|
|
1025
|
+
* Used by useRead and injectRead hooks.
|
|
1026
|
+
*/
|
|
1027
|
+
type ReadClient<TSchema, TDefaultError = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => HasGetMethod<TSchema, TPath> extends true ? ReadPathMethods<TSchema, TPath, TDefaultError> : never;
|
|
1028
|
+
/**
|
|
1029
|
+
* Mutation methods (non-GET).
|
|
1030
|
+
*/
|
|
1031
|
+
type MutationMethod = "POST" | "PUT" | "PATCH" | "DELETE";
|
|
1032
|
+
/**
|
|
1033
|
+
* Write-only client type that only exposes mutation methods (POST, PUT, PATCH, DELETE).
|
|
1034
|
+
* Used by useWrite/injectWrite hooks to ensure only mutation operations are selected.
|
|
1035
|
+
*/
|
|
1036
|
+
type WritePathMethods<TSchema, TPath extends string, TDefaultError> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? Simplify<{
|
|
1037
|
+
[M in MutationMethod as M extends keyof TSchema[TKey] ? M : never]: M extends keyof TSchema[TKey] ? MethodFn<TSchema[TKey][M], TDefaultError, TPath> : never;
|
|
1038
|
+
}> : never : never;
|
|
1039
|
+
/**
|
|
1040
|
+
* Check if a schema path has any mutation methods.
|
|
1041
|
+
*/
|
|
1042
|
+
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;
|
|
1043
|
+
/**
|
|
1044
|
+
* Extract paths that have mutation methods.
|
|
1045
|
+
*/
|
|
1046
|
+
type WritePaths<TSchema> = {
|
|
1047
|
+
[K in keyof TSchema & string]: Extract<keyof TSchema[K], MutationMethod> extends never ? never : K;
|
|
1048
|
+
}[keyof TSchema & string];
|
|
1049
|
+
/**
|
|
1050
|
+
* A write-only API client that only exposes mutation methods (POST, PUT, PATCH, DELETE).
|
|
1051
|
+
* Used by useWrite and injectWrite hooks.
|
|
1052
|
+
*/
|
|
1053
|
+
type WriteClient<TSchema, TDefaultError = unknown> = <TPath extends WritePaths<TSchema> | (string & {})>(path: TPath) => HasMutationMethod<TSchema, TPath> extends true ? WritePathMethods<TSchema, TPath, TDefaultError> : never;
|
|
920
1054
|
|
|
921
1055
|
type PluginArray = readonly SpooshPlugin<PluginTypeConfig>[];
|
|
922
1056
|
interface SpooshConfig<TPlugins extends PluginArray = PluginArray> {
|
|
@@ -925,7 +1059,7 @@ interface SpooshConfig<TPlugins extends PluginArray = PluginArray> {
|
|
|
925
1059
|
plugins?: TPlugins;
|
|
926
1060
|
}
|
|
927
1061
|
type SpooshInstance<TSchema = unknown, TDefaultError = unknown, TPlugins extends PluginArray = PluginArray> = {
|
|
928
|
-
api: SpooshClient<TSchema, TDefaultError
|
|
1062
|
+
api: SpooshClient<TSchema, TDefaultError>;
|
|
929
1063
|
stateManager: StateManager;
|
|
930
1064
|
eventEmitter: EventEmitter;
|
|
931
1065
|
pluginExecutor: PluginExecutor;
|
|
@@ -953,7 +1087,7 @@ type SpooshInstance<TSchema = unknown, TDefaultError = unknown, TPlugins extends
|
|
|
953
1087
|
* .use([cachePlugin(), retryPlugin()]);
|
|
954
1088
|
*
|
|
955
1089
|
* const { api } = client;
|
|
956
|
-
* const response = await api.
|
|
1090
|
+
* const response = await api("posts").GET();
|
|
957
1091
|
* ```
|
|
958
1092
|
*
|
|
959
1093
|
* @example With default options
|
|
@@ -971,6 +1105,10 @@ type SpooshInstance<TSchema = unknown, TDefaultError = unknown, TPlugins extends
|
|
|
971
1105
|
* .use([cachePlugin(), retryPlugin()]);
|
|
972
1106
|
*
|
|
973
1107
|
* const { useRead, useWrite } = createReactSpoosh(client);
|
|
1108
|
+
*
|
|
1109
|
+
* // In component
|
|
1110
|
+
* const { data } = useRead((api) => api("posts").GET());
|
|
1111
|
+
* const { trigger } = useWrite((api) => api("posts").POST);
|
|
974
1112
|
* ```
|
|
975
1113
|
*
|
|
976
1114
|
* @since 0.1.0
|
|
@@ -1056,16 +1194,16 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
|
|
|
1056
1194
|
* const { api } = client;
|
|
1057
1195
|
*
|
|
1058
1196
|
* // GET request
|
|
1059
|
-
* const { data } = await api.
|
|
1197
|
+
* const { data } = await api("posts").GET();
|
|
1060
1198
|
*
|
|
1061
1199
|
* // POST request with body
|
|
1062
|
-
* const { data } = await api.
|
|
1200
|
+
* const { data } = await api("posts").POST({ body: { title: 'Hello' } });
|
|
1063
1201
|
*
|
|
1064
1202
|
* // Dynamic path parameters
|
|
1065
|
-
* const { data } = await api.
|
|
1203
|
+
* const { data } = await api("posts/:id").GET({ params: { id: postId } });
|
|
1066
1204
|
* ```
|
|
1067
1205
|
*/
|
|
1068
|
-
get api(): SpooshClient<TSchema, TError
|
|
1206
|
+
get api(): SpooshClient<TSchema, TError>;
|
|
1069
1207
|
/**
|
|
1070
1208
|
* State manager for cache and state operations.
|
|
1071
1209
|
*
|
|
@@ -1076,7 +1214,7 @@ declare class Spoosh<TSchema = unknown, TError = unknown, TPlugins extends Plugi
|
|
|
1076
1214
|
* const { stateManager } = client;
|
|
1077
1215
|
*
|
|
1078
1216
|
* // Get cached data
|
|
1079
|
-
* const cache = stateManager.getCache('posts
|
|
1217
|
+
* const cache = stateManager.getCache('posts.GET');
|
|
1080
1218
|
*
|
|
1081
1219
|
* // Invalidate cache by tag
|
|
1082
1220
|
* stateManager.invalidate(['posts']);
|
|
@@ -1162,16 +1300,17 @@ type SpooshClientConfig = {
|
|
|
1162
1300
|
*
|
|
1163
1301
|
* @example
|
|
1164
1302
|
* ```ts
|
|
1165
|
-
* type ApiSchema = {
|
|
1166
|
-
* posts: {
|
|
1167
|
-
*
|
|
1168
|
-
*
|
|
1169
|
-
* _: {
|
|
1170
|
-
* $get: Endpoint<Post>;
|
|
1171
|
-
* $delete: Endpoint<void>;
|
|
1172
|
-
* };
|
|
1303
|
+
* type ApiSchema = SpooshSchema<{
|
|
1304
|
+
* "posts": {
|
|
1305
|
+
* GET: { data: Post[] };
|
|
1306
|
+
* POST: { data: Post; body: CreatePostBody };
|
|
1173
1307
|
* };
|
|
1174
|
-
*
|
|
1308
|
+
* "posts/:id": {
|
|
1309
|
+
* GET: { data: Post };
|
|
1310
|
+
* PUT: { data: Post; body: UpdatePostBody };
|
|
1311
|
+
* DELETE: { data: void };
|
|
1312
|
+
* };
|
|
1313
|
+
* }>;
|
|
1175
1314
|
*
|
|
1176
1315
|
* type ApiError = {
|
|
1177
1316
|
* message: string;
|
|
@@ -1181,9 +1320,10 @@ type SpooshClientConfig = {
|
|
|
1181
1320
|
* baseUrl: "/api",
|
|
1182
1321
|
* });
|
|
1183
1322
|
*
|
|
1184
|
-
* // Type-safe API calls
|
|
1185
|
-
* const { data } = await api.
|
|
1186
|
-
* const { data: post } = await api
|
|
1323
|
+
* // Type-safe API calls with path strings
|
|
1324
|
+
* const { data } = await api("posts").GET();
|
|
1325
|
+
* const { data: post } = await api("posts/123").GET();
|
|
1326
|
+
* await api("posts/:id").GET({ params: { id: 123 } });
|
|
1187
1327
|
* ```
|
|
1188
1328
|
*/
|
|
1189
1329
|
declare function createClient<TSchema, TDefaultError = unknown>(config: SpooshClientConfig): SpooshClient<TSchema, TDefaultError>;
|
|
@@ -1208,6 +1348,11 @@ declare function mergeHeaders(defaultHeaders?: HeadersInitOrGetter, requestHeade
|
|
|
1208
1348
|
declare function setHeaders(requestOptions: {
|
|
1209
1349
|
headers?: HeadersInitOrGetter;
|
|
1210
1350
|
}, newHeaders: Record<string, string>): void;
|
|
1351
|
+
/**
|
|
1352
|
+
* Extracts the Content-Type header value from HeadersInit.
|
|
1353
|
+
* Returns undefined if no Content-Type is set.
|
|
1354
|
+
*/
|
|
1355
|
+
declare function getContentType(headers?: HeadersInit): string | undefined;
|
|
1211
1356
|
|
|
1212
1357
|
declare function objectToFormData(obj: Record<string, unknown>): FormData;
|
|
1213
1358
|
|
|
@@ -1230,41 +1375,30 @@ declare function resolvePath(path: string[], params: Record<string, string | num
|
|
|
1230
1375
|
type ProxyHandlerConfig<TOptions = SpooshOptions> = {
|
|
1231
1376
|
baseUrl: string;
|
|
1232
1377
|
defaultOptions: TOptions;
|
|
1233
|
-
path?: string[];
|
|
1234
1378
|
fetchExecutor?: FetchExecutor<TOptions, AnyRequestOptions>;
|
|
1235
1379
|
nextTags?: boolean;
|
|
1236
1380
|
};
|
|
1237
1381
|
/**
|
|
1238
|
-
* Creates
|
|
1239
|
-
*
|
|
1240
|
-
* This proxy intercepts property access and function calls to build URL paths,
|
|
1241
|
-
* then executes fetch requests when an HTTP method ($get, $post, etc.) is called.
|
|
1242
|
-
*
|
|
1243
|
-
* Used internally by `createClient` and `createSpoosh` to create typed API clients.
|
|
1382
|
+
* Creates an API client proxy that uses path strings instead of chained property access.
|
|
1383
|
+
* Methods use HTTP names directly: GET, POST, PUT, PATCH, DELETE.
|
|
1244
1384
|
*
|
|
1245
1385
|
* @param config - Proxy handler configuration
|
|
1246
|
-
*
|
|
1247
|
-
* @returns A proxy object typed as TSchema that executes real HTTP requests
|
|
1386
|
+
* @returns A function that takes a path and returns an object with HTTP method functions
|
|
1248
1387
|
*
|
|
1249
1388
|
* @example
|
|
1250
1389
|
* ```ts
|
|
1251
1390
|
* const api = createProxyHandler<ApiSchema>({ baseUrl: '/api', defaultOptions: {} });
|
|
1252
1391
|
*
|
|
1253
|
-
* //
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1256
|
-
* await api.
|
|
1257
|
-
*
|
|
1258
|
-
* // Dynamic segments via function call:
|
|
1259
|
-
* // api.posts(123).$get() or api.posts('123').$get()
|
|
1260
|
-
* // Executes: GET /api/posts/123
|
|
1261
|
-
* await api.posts(123).$get();
|
|
1392
|
+
* // Call with path string
|
|
1393
|
+
* await api("posts").GET();
|
|
1394
|
+
* await api("posts/123").GET();
|
|
1395
|
+
* await api("posts/:id").GET({ params: { id: 123 } });
|
|
1262
1396
|
* ```
|
|
1263
1397
|
*/
|
|
1264
|
-
declare function createProxyHandler<TSchema
|
|
1398
|
+
declare function createProxyHandler<TSchema, TDefaultError = unknown, TOptions = SpooshOptions>(config: ProxyHandlerConfig<TOptions>): SpooshClient<TSchema, TDefaultError>;
|
|
1265
1399
|
|
|
1266
1400
|
/** All supported HTTP method keys used in the API client */
|
|
1267
|
-
declare const HTTP_METHODS: readonly ["
|
|
1401
|
+
declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
1268
1402
|
/** Union type of all HTTP method keys */
|
|
1269
1403
|
type HttpMethodKey = (typeof HTTP_METHODS)[number];
|
|
1270
1404
|
/**
|
|
@@ -1275,9 +1409,9 @@ type HttpMethodKey = (typeof HTTP_METHODS)[number];
|
|
|
1275
1409
|
type SelectorFunction = (() => Promise<{
|
|
1276
1410
|
data: undefined;
|
|
1277
1411
|
}>) & {
|
|
1278
|
-
/** The path
|
|
1279
|
-
__selectorPath?: string
|
|
1280
|
-
/** The HTTP method selected (e.g., '
|
|
1412
|
+
/** The path string for this endpoint (e.g., 'posts', 'posts/:id') */
|
|
1413
|
+
__selectorPath?: string;
|
|
1414
|
+
/** The HTTP method selected (e.g., 'GET', 'POST') */
|
|
1281
1415
|
__selectorMethod?: string;
|
|
1282
1416
|
};
|
|
1283
1417
|
/**
|
|
@@ -1286,9 +1420,9 @@ type SelectorFunction = (() => Promise<{
|
|
|
1286
1420
|
* Captured when an HTTP method is invoked with options.
|
|
1287
1421
|
*/
|
|
1288
1422
|
type CapturedCall = {
|
|
1289
|
-
/** Path
|
|
1290
|
-
path: string
|
|
1291
|
-
/** HTTP method called (e.g., '
|
|
1423
|
+
/** Path string to the endpoint (e.g., 'posts/:id') */
|
|
1424
|
+
path: string;
|
|
1425
|
+
/** HTTP method called (e.g., 'GET', 'POST') */
|
|
1292
1426
|
method: string;
|
|
1293
1427
|
/** Request options passed to the method (query, body, params, etc.) */
|
|
1294
1428
|
options: unknown;
|
|
@@ -1299,8 +1433,8 @@ type CapturedCall = {
|
|
|
1299
1433
|
* Captured when an HTTP method is accessed but not yet called.
|
|
1300
1434
|
*/
|
|
1301
1435
|
type SelectedEndpoint = {
|
|
1302
|
-
/** Path
|
|
1303
|
-
path: string
|
|
1436
|
+
/** Path string to the endpoint */
|
|
1437
|
+
path: string;
|
|
1304
1438
|
/** HTTP method selected */
|
|
1305
1439
|
method: string;
|
|
1306
1440
|
};
|
|
@@ -1330,41 +1464,41 @@ type SelectorResult = {
|
|
|
1330
1464
|
* const proxy = createSelectorProxy<ApiSchema>();
|
|
1331
1465
|
*
|
|
1332
1466
|
* // Select an endpoint
|
|
1333
|
-
* const endpoint = proxy.
|
|
1467
|
+
* const endpoint = proxy("posts").GET;
|
|
1334
1468
|
*
|
|
1335
1469
|
* // Extract path for cache operations
|
|
1336
|
-
* const path = extractPathFromSelector(endpoint); //
|
|
1337
|
-
* const method = extractMethodFromSelector(endpoint); // '
|
|
1470
|
+
* const path = extractPathFromSelector(endpoint); // 'posts'
|
|
1471
|
+
* const method = extractMethodFromSelector(endpoint); // 'GET'
|
|
1338
1472
|
* ```
|
|
1339
1473
|
*
|
|
1340
1474
|
* @internal onCapture - Used internally by framework adapters
|
|
1341
1475
|
*/
|
|
1342
1476
|
declare function createSelectorProxy<TSchema>(onCapture?: (result: SelectorResult) => void): TSchema;
|
|
1343
1477
|
/**
|
|
1344
|
-
* Extracts the path
|
|
1478
|
+
* Extracts the path from a SelectorFunction.
|
|
1345
1479
|
*
|
|
1346
1480
|
* @param fn - A SelectorFunction returned from `createSelectorProxy`
|
|
1347
|
-
* @returns
|
|
1481
|
+
* @returns The path string (e.g., 'posts', 'posts/:id')
|
|
1348
1482
|
*
|
|
1349
1483
|
* @example
|
|
1350
1484
|
* ```ts
|
|
1351
1485
|
* const proxy = createSelectorProxy<ApiSchema>();
|
|
1352
|
-
* const path = extractPathFromSelector(proxy
|
|
1353
|
-
* // path =
|
|
1486
|
+
* const path = extractPathFromSelector(proxy("posts").GET);
|
|
1487
|
+
* // path = 'posts'
|
|
1354
1488
|
* ```
|
|
1355
1489
|
*/
|
|
1356
|
-
declare function extractPathFromSelector(fn: unknown): string
|
|
1490
|
+
declare function extractPathFromSelector(fn: unknown): string;
|
|
1357
1491
|
/**
|
|
1358
1492
|
* Extracts the HTTP method from a SelectorFunction.
|
|
1359
1493
|
*
|
|
1360
1494
|
* @param fn - A SelectorFunction returned from `createSelectorProxy`
|
|
1361
|
-
* @returns The HTTP method string (e.g., '
|
|
1495
|
+
* @returns The HTTP method string (e.g., 'GET', 'POST') or undefined
|
|
1362
1496
|
*
|
|
1363
1497
|
* @example
|
|
1364
1498
|
* ```ts
|
|
1365
1499
|
* const proxy = createSelectorProxy<ApiSchema>();
|
|
1366
|
-
* const method = extractMethodFromSelector(proxy
|
|
1367
|
-
* // method = '
|
|
1500
|
+
* const method = extractMethodFromSelector(proxy("posts").POST);
|
|
1501
|
+
* // method = 'POST'
|
|
1368
1502
|
* ```
|
|
1369
1503
|
*/
|
|
1370
1504
|
declare function extractMethodFromSelector(fn: unknown): string | undefined;
|
|
@@ -1463,4 +1597,4 @@ type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
|
|
|
1463
1597
|
};
|
|
1464
1598
|
declare function createInfiniteReadController<TData, TItem, TError, TRequest extends InfiniteRequestOptions = InfiniteRequestOptions>(options: CreateInfiniteReadOptions<TData, TItem, TError, TRequest>): InfiniteReadController<TData, TItem, TError>;
|
|
1465
1599
|
|
|
1466
|
-
export { type AnyRequestOptions, 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
|
|
1600
|
+
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 MutationSchemaHelper, 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 QuerySchemaHelper, type ReadClient, 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, Spoosh, type SpooshClient, type SpooshConfig, type SpooshInstance, type SpooshMiddleware, type SpooshOptions, type SpooshOptionsExtra, type SpooshPlugin, type SpooshResponse, type SpooshSchema, type StateManager, type TagOptions, type WriteClient, applyMiddlewares, buildUrl, composeMiddlewares, containsFile, createClient, createEventEmitter, createInfiniteReadController, createInitialState, createMiddleware, createOperationController, createPluginExecutor, createPluginRegistry, createProxyHandler, createSelectorProxy, createStateManager, executeFetch, extractMethodFromSelector, extractPathFromSelector, generateTags, getContentType, isJsonBody, mergeHeaders, objectToFormData, objectToUrlEncoded, resolveHeadersToRecord, resolvePath, resolveTags, setHeaders, sortObjectKeys };
|