@spoosh/core 0.5.0 → 0.7.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 +398 -257
- package/dist/index.d.ts +398 -257
- package/dist/index.js +120 -115
- package/dist/index.mjs +120 -115
- package/package.json +1 -1
package/dist/index.d.mts
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
|
|
@@ -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
|
|
|
@@ -1215,14 +1360,21 @@ declare function objectToUrlEncoded(obj: Record<string, unknown>): string;
|
|
|
1215
1360
|
|
|
1216
1361
|
declare function sortObjectKeys(obj: unknown, seen?: WeakSet<object>): unknown;
|
|
1217
1362
|
|
|
1363
|
+
type TagMode = "all" | "self" | "none";
|
|
1364
|
+
type TagModeInArray = "all" | "self";
|
|
1218
1365
|
/**
|
|
1219
1366
|
* Common tag options used across plugins and operations.
|
|
1220
1367
|
*/
|
|
1221
1368
|
type TagOptions = {
|
|
1222
|
-
/**
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1369
|
+
/**
|
|
1370
|
+
* Unified tag option (follows invalidation pattern)
|
|
1371
|
+
* - String: mode only ('all' | 'self' | 'none')
|
|
1372
|
+
* - Array: custom tags only OR [mode keyword mixed with custom tags]
|
|
1373
|
+
* - If array contains 'all' or 'self', it's treated as mode + tags
|
|
1374
|
+
* - Otherwise, it's custom tags only (replaces auto-generated tags)
|
|
1375
|
+
* - 'none' keyword should NOT be used in arrays (use string 'none' instead)
|
|
1376
|
+
*/
|
|
1377
|
+
tags?: TagMode | (TagModeInArray | (string & {}))[];
|
|
1226
1378
|
};
|
|
1227
1379
|
declare function resolveTags(options: TagOptions | undefined, resolvedPath: string[]): string[];
|
|
1228
1380
|
declare function resolvePath(path: string[], params: Record<string, string | number> | undefined): string[];
|
|
@@ -1230,41 +1382,30 @@ declare function resolvePath(path: string[], params: Record<string, string | num
|
|
|
1230
1382
|
type ProxyHandlerConfig<TOptions = SpooshOptions> = {
|
|
1231
1383
|
baseUrl: string;
|
|
1232
1384
|
defaultOptions: TOptions;
|
|
1233
|
-
path?: string[];
|
|
1234
1385
|
fetchExecutor?: FetchExecutor<TOptions, AnyRequestOptions>;
|
|
1235
1386
|
nextTags?: boolean;
|
|
1236
1387
|
};
|
|
1237
1388
|
/**
|
|
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.
|
|
1389
|
+
* Creates an API client proxy that uses path strings instead of chained property access.
|
|
1390
|
+
* Methods use HTTP names directly: GET, POST, PUT, PATCH, DELETE.
|
|
1244
1391
|
*
|
|
1245
1392
|
* @param config - Proxy handler configuration
|
|
1246
|
-
*
|
|
1247
|
-
* @returns A proxy object typed as TSchema that executes real HTTP requests
|
|
1393
|
+
* @returns A function that takes a path and returns an object with HTTP method functions
|
|
1248
1394
|
*
|
|
1249
1395
|
* @example
|
|
1250
1396
|
* ```ts
|
|
1251
1397
|
* const api = createProxyHandler<ApiSchema>({ baseUrl: '/api', defaultOptions: {} });
|
|
1252
1398
|
*
|
|
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();
|
|
1399
|
+
* // Call with path string
|
|
1400
|
+
* await api("posts").GET();
|
|
1401
|
+
* await api("posts/123").GET();
|
|
1402
|
+
* await api("posts/:id").GET({ params: { id: 123 } });
|
|
1262
1403
|
* ```
|
|
1263
1404
|
*/
|
|
1264
|
-
declare function createProxyHandler<TSchema
|
|
1405
|
+
declare function createProxyHandler<TSchema, TDefaultError = unknown, TOptions = SpooshOptions>(config: ProxyHandlerConfig<TOptions>): SpooshClient<TSchema, TDefaultError>;
|
|
1265
1406
|
|
|
1266
1407
|
/** All supported HTTP method keys used in the API client */
|
|
1267
|
-
declare const HTTP_METHODS: readonly ["
|
|
1408
|
+
declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
1268
1409
|
/** Union type of all HTTP method keys */
|
|
1269
1410
|
type HttpMethodKey = (typeof HTTP_METHODS)[number];
|
|
1270
1411
|
/**
|
|
@@ -1275,9 +1416,9 @@ type HttpMethodKey = (typeof HTTP_METHODS)[number];
|
|
|
1275
1416
|
type SelectorFunction = (() => Promise<{
|
|
1276
1417
|
data: undefined;
|
|
1277
1418
|
}>) & {
|
|
1278
|
-
/** The path
|
|
1279
|
-
__selectorPath?: string
|
|
1280
|
-
/** The HTTP method selected (e.g., '
|
|
1419
|
+
/** The path string for this endpoint (e.g., 'posts', 'posts/:id') */
|
|
1420
|
+
__selectorPath?: string;
|
|
1421
|
+
/** The HTTP method selected (e.g., 'GET', 'POST') */
|
|
1281
1422
|
__selectorMethod?: string;
|
|
1282
1423
|
};
|
|
1283
1424
|
/**
|
|
@@ -1286,9 +1427,9 @@ type SelectorFunction = (() => Promise<{
|
|
|
1286
1427
|
* Captured when an HTTP method is invoked with options.
|
|
1287
1428
|
*/
|
|
1288
1429
|
type CapturedCall = {
|
|
1289
|
-
/** Path
|
|
1290
|
-
path: string
|
|
1291
|
-
/** HTTP method called (e.g., '
|
|
1430
|
+
/** Path string to the endpoint (e.g., 'posts/:id') */
|
|
1431
|
+
path: string;
|
|
1432
|
+
/** HTTP method called (e.g., 'GET', 'POST') */
|
|
1292
1433
|
method: string;
|
|
1293
1434
|
/** Request options passed to the method (query, body, params, etc.) */
|
|
1294
1435
|
options: unknown;
|
|
@@ -1299,8 +1440,8 @@ type CapturedCall = {
|
|
|
1299
1440
|
* Captured when an HTTP method is accessed but not yet called.
|
|
1300
1441
|
*/
|
|
1301
1442
|
type SelectedEndpoint = {
|
|
1302
|
-
/** Path
|
|
1303
|
-
path: string
|
|
1443
|
+
/** Path string to the endpoint */
|
|
1444
|
+
path: string;
|
|
1304
1445
|
/** HTTP method selected */
|
|
1305
1446
|
method: string;
|
|
1306
1447
|
};
|
|
@@ -1330,41 +1471,41 @@ type SelectorResult = {
|
|
|
1330
1471
|
* const proxy = createSelectorProxy<ApiSchema>();
|
|
1331
1472
|
*
|
|
1332
1473
|
* // Select an endpoint
|
|
1333
|
-
* const endpoint = proxy.
|
|
1474
|
+
* const endpoint = proxy("posts").GET;
|
|
1334
1475
|
*
|
|
1335
1476
|
* // Extract path for cache operations
|
|
1336
|
-
* const path = extractPathFromSelector(endpoint); //
|
|
1337
|
-
* const method = extractMethodFromSelector(endpoint); // '
|
|
1477
|
+
* const path = extractPathFromSelector(endpoint); // 'posts'
|
|
1478
|
+
* const method = extractMethodFromSelector(endpoint); // 'GET'
|
|
1338
1479
|
* ```
|
|
1339
1480
|
*
|
|
1340
1481
|
* @internal onCapture - Used internally by framework adapters
|
|
1341
1482
|
*/
|
|
1342
1483
|
declare function createSelectorProxy<TSchema>(onCapture?: (result: SelectorResult) => void): TSchema;
|
|
1343
1484
|
/**
|
|
1344
|
-
* Extracts the path
|
|
1485
|
+
* Extracts the path from a SelectorFunction.
|
|
1345
1486
|
*
|
|
1346
1487
|
* @param fn - A SelectorFunction returned from `createSelectorProxy`
|
|
1347
|
-
* @returns
|
|
1488
|
+
* @returns The path string (e.g., 'posts', 'posts/:id')
|
|
1348
1489
|
*
|
|
1349
1490
|
* @example
|
|
1350
1491
|
* ```ts
|
|
1351
1492
|
* const proxy = createSelectorProxy<ApiSchema>();
|
|
1352
|
-
* const path = extractPathFromSelector(proxy
|
|
1353
|
-
* // path =
|
|
1493
|
+
* const path = extractPathFromSelector(proxy("posts").GET);
|
|
1494
|
+
* // path = 'posts'
|
|
1354
1495
|
* ```
|
|
1355
1496
|
*/
|
|
1356
|
-
declare function extractPathFromSelector(fn: unknown): string
|
|
1497
|
+
declare function extractPathFromSelector(fn: unknown): string;
|
|
1357
1498
|
/**
|
|
1358
1499
|
* Extracts the HTTP method from a SelectorFunction.
|
|
1359
1500
|
*
|
|
1360
1501
|
* @param fn - A SelectorFunction returned from `createSelectorProxy`
|
|
1361
|
-
* @returns The HTTP method string (e.g., '
|
|
1502
|
+
* @returns The HTTP method string (e.g., 'GET', 'POST') or undefined
|
|
1362
1503
|
*
|
|
1363
1504
|
* @example
|
|
1364
1505
|
* ```ts
|
|
1365
1506
|
* const proxy = createSelectorProxy<ApiSchema>();
|
|
1366
|
-
* const method = extractMethodFromSelector(proxy
|
|
1367
|
-
* // method = '
|
|
1507
|
+
* const method = extractMethodFromSelector(proxy("posts").POST);
|
|
1508
|
+
* // method = 'POST'
|
|
1368
1509
|
* ```
|
|
1369
1510
|
*/
|
|
1370
1511
|
declare function extractMethodFromSelector(fn: unknown): string | undefined;
|
|
@@ -1463,4 +1604,4 @@ type CreateInfiniteReadOptions<TData, TItem, TError, TRequest> = {
|
|
|
1463
1604
|
};
|
|
1464
1605
|
declare function createInfiniteReadController<TData, TItem, TError, TRequest extends InfiniteRequestOptions = InfiniteRequestOptions>(options: CreateInfiniteReadOptions<TData, TItem, TError, TRequest>): InfiniteReadController<TData, TItem, TError>;
|
|
1465
1606
|
|
|
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
|
|
1607
|
+
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 TagMode, 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 };
|