@fetchkit/ffetch 5.0.1 → 5.1.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.
@@ -0,0 +1,12 @@
1
+ import { C as ClientPlugin } from '../plugins-DqBQVM4I.cjs';
2
+
3
+ type ResponseShortcuts = {
4
+ json: <T = unknown>() => Promise<T>;
5
+ text: () => Promise<string>;
6
+ blob: () => Promise<Blob>;
7
+ arrayBuffer: () => Promise<ArrayBuffer>;
8
+ formData: () => Promise<FormData>;
9
+ };
10
+ declare function responseShortcutsPlugin(): ClientPlugin<Record<never, never>, ResponseShortcuts>;
11
+
12
+ export { type ResponseShortcuts, responseShortcutsPlugin };
@@ -0,0 +1,12 @@
1
+ import { C as ClientPlugin } from '../plugins-DqBQVM4I.js';
2
+
3
+ type ResponseShortcuts = {
4
+ json: <T = unknown>() => Promise<T>;
5
+ text: () => Promise<string>;
6
+ blob: () => Promise<Blob>;
7
+ arrayBuffer: () => Promise<ArrayBuffer>;
8
+ formData: () => Promise<FormData>;
9
+ };
10
+ declare function responseShortcutsPlugin(): ClientPlugin<Record<never, never>, ResponseShortcuts>;
11
+
12
+ export { type ResponseShortcuts, responseShortcutsPlugin };
@@ -0,0 +1,66 @@
1
+ // src/plugins/response-shortcuts.ts
2
+ function attachResponseShortcuts(promise) {
3
+ const decorated = promise;
4
+ if (decorated.__ffetchResponseShortcutsDecorated__) {
5
+ return decorated;
6
+ }
7
+ Object.defineProperties(decorated, {
8
+ json: {
9
+ value: function json() {
10
+ return this.then((response) => response.json());
11
+ },
12
+ writable: false,
13
+ enumerable: false,
14
+ configurable: false
15
+ },
16
+ text: {
17
+ value: function text() {
18
+ return this.then((response) => response.text());
19
+ },
20
+ writable: false,
21
+ enumerable: false,
22
+ configurable: false
23
+ },
24
+ blob: {
25
+ value: function blob() {
26
+ return this.then((response) => response.blob());
27
+ },
28
+ writable: false,
29
+ enumerable: false,
30
+ configurable: false
31
+ },
32
+ arrayBuffer: {
33
+ value: function arrayBuffer() {
34
+ return this.then((response) => response.arrayBuffer());
35
+ },
36
+ writable: false,
37
+ enumerable: false,
38
+ configurable: false
39
+ },
40
+ formData: {
41
+ value: function formData() {
42
+ return this.then((response) => response.formData());
43
+ },
44
+ writable: false,
45
+ enumerable: false,
46
+ configurable: false
47
+ },
48
+ __ffetchResponseShortcutsDecorated__: {
49
+ value: true,
50
+ writable: false,
51
+ enumerable: false,
52
+ configurable: false
53
+ }
54
+ });
55
+ return decorated;
56
+ }
57
+ function responseShortcutsPlugin() {
58
+ return {
59
+ name: "response-shortcuts",
60
+ decoratePromise: (promise) => attachResponseShortcuts(promise)
61
+ };
62
+ }
63
+ export {
64
+ responseShortcutsPlugin
65
+ };
66
+ //# sourceMappingURL=response-shortcuts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugins/response-shortcuts.ts"],"sourcesContent":["import type { ClientPlugin } from '../plugins.js'\r\n\r\nexport type ResponseShortcuts = {\r\n json: <T = unknown>() => Promise<T>\r\n text: () => Promise<string>\r\n blob: () => Promise<Blob>\r\n arrayBuffer: () => Promise<ArrayBuffer>\r\n formData: () => Promise<FormData>\r\n}\r\n\r\ntype ResponseShortcutsPromise = Promise<Response> & ResponseShortcuts\r\n\r\ntype DecoratedPromise = ResponseShortcutsPromise & {\r\n __ffetchResponseShortcutsDecorated__?: true\r\n}\r\n\r\nfunction attachResponseShortcuts(\r\n promise: Promise<Response>\r\n): ResponseShortcutsPromise {\r\n const decorated = promise as DecoratedPromise\r\n\r\n if (decorated.__ffetchResponseShortcutsDecorated__) {\r\n return decorated\r\n }\r\n\r\n Object.defineProperties(decorated, {\r\n json: {\r\n value: function json<T = unknown>(this: Promise<Response>) {\r\n return this.then((response) => response.json() as Promise<T>)\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n text: {\r\n value: function text(this: Promise<Response>) {\r\n return this.then((response) => response.text())\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n blob: {\r\n value: function blob(this: Promise<Response>) {\r\n return this.then((response) => response.blob())\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n arrayBuffer: {\r\n value: function arrayBuffer(this: Promise<Response>) {\r\n return this.then((response) => response.arrayBuffer())\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n formData: {\r\n value: function formData(this: Promise<Response>) {\r\n return this.then((response) => response.formData())\r\n },\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n __ffetchResponseShortcutsDecorated__: {\r\n value: true,\r\n writable: false,\r\n enumerable: false,\r\n configurable: false,\r\n },\r\n })\r\n\r\n return decorated\r\n}\r\n\r\nexport function responseShortcutsPlugin(): ClientPlugin<\r\n Record<never, never>,\r\n ResponseShortcuts\r\n> {\r\n return {\r\n name: 'response-shortcuts',\r\n decoratePromise: (promise) => attachResponseShortcuts(promise),\r\n }\r\n}\r\n"],"mappings":";AAgBA,SAAS,wBACP,SAC0B;AAC1B,QAAM,YAAY;AAElB,MAAI,UAAU,sCAAsC;AAClD,WAAO;AAAA,EACT;AAEA,SAAO,iBAAiB,WAAW;AAAA,IACjC,MAAM;AAAA,MACJ,OAAO,SAAS,OAA2C;AACzD,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,KAAK,CAAe;AAAA,MAC9D;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,MACJ,OAAO,SAAS,OAA8B;AAC5C,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,KAAK,CAAC;AAAA,MAChD;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,MACJ,OAAO,SAAS,OAA8B;AAC5C,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,KAAK,CAAC;AAAA,MAChD;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,aAAa;AAAA,MACX,OAAO,SAAS,cAAqC;AACnD,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,YAAY,CAAC;AAAA,MACvD;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,UAAU;AAAA,MACR,OAAO,SAAS,WAAkC;AAChD,eAAO,KAAK,KAAK,CAAC,aAAa,SAAS,SAAS,CAAC;AAAA,MACpD;AAAA,MACA,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,IACA,sCAAsC;AAAA,MACpC,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,cAAc;AAAA,IAChB;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEO,SAAS,0BAGd;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,iBAAiB,CAAC,YAAY,wBAAwB,OAAO;AAAA,EAC/D;AACF;","names":[]}
@@ -1,8 +1,11 @@
1
1
  type PluginState = Record<string, unknown>;
2
2
  type PluginExtensionBase = Record<PropertyKey, unknown>;
3
+ type PluginRequestPromiseExtensionBase = Record<PropertyKey, unknown>;
3
4
  type UnionToIntersection<U> = (U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never;
4
5
  type PluginExtensionOf<P> = P extends ClientPlugin<infer TExtension> ? TExtension : Record<never, never>;
6
+ type PluginRequestPromiseExtensionOf<P> = P extends ClientPlugin<PluginExtensionBase, infer TRequestPromiseExtension> ? TRequestPromiseExtension : Record<never, never>;
5
7
  type PluginExtensions<TPlugins extends readonly ClientPlugin<PluginExtensionBase>[]> = Extract<UnionToIntersection<PluginExtensionOf<TPlugins[number]>>, object>;
8
+ type PluginRequestPromiseExtensions<TPlugins extends readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[]> = Extract<UnionToIntersection<PluginRequestPromiseExtensionOf<TPlugins[number]>>, object>;
6
9
  type PluginSetupContext<TExtension extends PluginExtensionBase = Record<never, never>> = {
7
10
  defineExtension: <K extends keyof TExtension>(key: K, descriptor: {
8
11
  value: TExtension[K];
@@ -44,15 +47,16 @@ type PluginRequestContext = {
44
47
  metadata: PluginRequestMetadata;
45
48
  };
46
49
  type PluginDispatch = (ctx: PluginRequestContext) => Promise<Response>;
47
- type ClientPlugin<TExtension extends PluginExtensionBase = Record<never, never>> = {
50
+ type ClientPlugin<TExtension extends PluginExtensionBase = Record<never, never>, TRequestPromiseExtension extends PluginRequestPromiseExtensionBase = Record<never, never>> = {
48
51
  name: string;
49
52
  order?: number;
50
53
  setup?: (ctx: PluginSetupContext<TExtension>) => void;
51
54
  preRequest?: (ctx: PluginRequestContext) => void | Promise<void>;
52
55
  wrapDispatch?: (next: PluginDispatch) => PluginDispatch;
56
+ decoratePromise?: (promise: Promise<Response>) => Promise<Response> & TRequestPromiseExtension;
53
57
  onSuccess?: (ctx: PluginRequestContext, response: Response) => void | Promise<void>;
54
58
  onError?: (ctx: PluginRequestContext, error: unknown) => void | Promise<void>;
55
59
  onFinally?: (ctx: PluginRequestContext) => void | Promise<void>;
56
60
  };
57
61
 
58
- export type { ClientPlugin as C, PluginExtensionBase as P, PluginExtensions as a, PluginRequestContext as b, PluginDispatch as c, PluginSetupContext as d };
62
+ export type { ClientPlugin as C, PluginExtensionBase as P, PluginRequestPromiseExtensionBase as a, PluginExtensions as b, PluginRequestPromiseExtensions as c, PluginRequestContext as d, PluginDispatch as e, PluginSetupContext as f };
@@ -1,8 +1,11 @@
1
1
  type PluginState = Record<string, unknown>;
2
2
  type PluginExtensionBase = Record<PropertyKey, unknown>;
3
+ type PluginRequestPromiseExtensionBase = Record<PropertyKey, unknown>;
3
4
  type UnionToIntersection<U> = (U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never;
4
5
  type PluginExtensionOf<P> = P extends ClientPlugin<infer TExtension> ? TExtension : Record<never, never>;
6
+ type PluginRequestPromiseExtensionOf<P> = P extends ClientPlugin<PluginExtensionBase, infer TRequestPromiseExtension> ? TRequestPromiseExtension : Record<never, never>;
5
7
  type PluginExtensions<TPlugins extends readonly ClientPlugin<PluginExtensionBase>[]> = Extract<UnionToIntersection<PluginExtensionOf<TPlugins[number]>>, object>;
8
+ type PluginRequestPromiseExtensions<TPlugins extends readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[]> = Extract<UnionToIntersection<PluginRequestPromiseExtensionOf<TPlugins[number]>>, object>;
6
9
  type PluginSetupContext<TExtension extends PluginExtensionBase = Record<never, never>> = {
7
10
  defineExtension: <K extends keyof TExtension>(key: K, descriptor: {
8
11
  value: TExtension[K];
@@ -44,15 +47,16 @@ type PluginRequestContext = {
44
47
  metadata: PluginRequestMetadata;
45
48
  };
46
49
  type PluginDispatch = (ctx: PluginRequestContext) => Promise<Response>;
47
- type ClientPlugin<TExtension extends PluginExtensionBase = Record<never, never>> = {
50
+ type ClientPlugin<TExtension extends PluginExtensionBase = Record<never, never>, TRequestPromiseExtension extends PluginRequestPromiseExtensionBase = Record<never, never>> = {
48
51
  name: string;
49
52
  order?: number;
50
53
  setup?: (ctx: PluginSetupContext<TExtension>) => void;
51
54
  preRequest?: (ctx: PluginRequestContext) => void | Promise<void>;
52
55
  wrapDispatch?: (next: PluginDispatch) => PluginDispatch;
56
+ decoratePromise?: (promise: Promise<Response>) => Promise<Response> & TRequestPromiseExtension;
53
57
  onSuccess?: (ctx: PluginRequestContext, response: Response) => void | Promise<void>;
54
58
  onError?: (ctx: PluginRequestContext, error: unknown) => void | Promise<void>;
55
59
  onFinally?: (ctx: PluginRequestContext) => void | Promise<void>;
56
60
  };
57
61
 
58
- export type { ClientPlugin as C, PluginExtensionBase as P, PluginExtensions as a, PluginRequestContext as b, PluginDispatch as c, PluginSetupContext as d };
62
+ export type { ClientPlugin as C, PluginExtensionBase as P, PluginRequestPromiseExtensionBase as a, PluginExtensions as b, PluginRequestPromiseExtensions as c, PluginRequestContext as d, PluginDispatch as e, PluginSetupContext as f };
@@ -0,0 +1,48 @@
1
+ import { C as ClientPlugin, P as PluginExtensionBase, a as PluginRequestPromiseExtensionBase } from './plugins-DqBQVM4I.cjs';
2
+
3
+ type Hooks = {
4
+ before?: (req: Request) => void | Promise<void>;
5
+ after?: (req: Request, res: Response) => void | Promise<void>;
6
+ onError?: (req: Request, err: unknown) => void | Promise<void>;
7
+ onRetry?: (req: Request, attempt: number, err?: unknown, res?: Response) => void | Promise<void>;
8
+ onTimeout?: (req: Request) => void | Promise<void>;
9
+ onAbort?: (req: Request) => void | Promise<void>;
10
+ onComplete?: (req: Request, res?: Response, err?: unknown) => void | Promise<void>;
11
+ transformRequest?: (req: Request) => Request | Promise<Request>;
12
+ transformResponse?: (res: Response, req: Request) => Response | Promise<Response>;
13
+ };
14
+
15
+ interface RetryContext {
16
+ attempt: number;
17
+ request: Request;
18
+ response?: Response;
19
+ error?: unknown;
20
+ }
21
+ interface CoreClientOptions {
22
+ timeout?: number;
23
+ retries?: number;
24
+ retryDelay?: number | ((ctx: RetryContext) => number);
25
+ shouldRetry?: (ctx: RetryContext) => boolean;
26
+ throwOnHttpError?: boolean;
27
+ hooks?: Hooks;
28
+ fetchHandler?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
29
+ }
30
+ interface FFetchOptions<TPlugins extends readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[]> extends CoreClientOptions {
31
+ plugins?: TPlugins;
32
+ }
33
+ type FFetchRequestOptions = CoreClientOptions;
34
+ type FFetchRequestPromise<TRequestPromiseExtensions extends object = Record<never, never>> = Promise<Response> & TRequestPromiseExtensions;
35
+ type FFetch<TExtensions extends object = Record<never, never>, TRequestPromiseExtensions extends object = Record<never, never>> = {
36
+ (input: RequestInfo | URL, init?: FFetchRequestInit): FFetchRequestPromise<TRequestPromiseExtensions>;
37
+ pendingRequests: PendingRequest[];
38
+ abortAll: () => void;
39
+ } & TExtensions;
40
+ interface FFetchRequestInit extends RequestInit, FFetchRequestOptions {
41
+ }
42
+ type PendingRequest = {
43
+ promise: Promise<Response>;
44
+ request: Request;
45
+ controller: AbortController;
46
+ };
47
+
48
+ export type { FFetchOptions as F, Hooks as H, FFetch as a, FFetchRequestInit as b };
@@ -0,0 +1,48 @@
1
+ import { C as ClientPlugin, P as PluginExtensionBase, a as PluginRequestPromiseExtensionBase } from './plugins-DqBQVM4I.js';
2
+
3
+ type Hooks = {
4
+ before?: (req: Request) => void | Promise<void>;
5
+ after?: (req: Request, res: Response) => void | Promise<void>;
6
+ onError?: (req: Request, err: unknown) => void | Promise<void>;
7
+ onRetry?: (req: Request, attempt: number, err?: unknown, res?: Response) => void | Promise<void>;
8
+ onTimeout?: (req: Request) => void | Promise<void>;
9
+ onAbort?: (req: Request) => void | Promise<void>;
10
+ onComplete?: (req: Request, res?: Response, err?: unknown) => void | Promise<void>;
11
+ transformRequest?: (req: Request) => Request | Promise<Request>;
12
+ transformResponse?: (res: Response, req: Request) => Response | Promise<Response>;
13
+ };
14
+
15
+ interface RetryContext {
16
+ attempt: number;
17
+ request: Request;
18
+ response?: Response;
19
+ error?: unknown;
20
+ }
21
+ interface CoreClientOptions {
22
+ timeout?: number;
23
+ retries?: number;
24
+ retryDelay?: number | ((ctx: RetryContext) => number);
25
+ shouldRetry?: (ctx: RetryContext) => boolean;
26
+ throwOnHttpError?: boolean;
27
+ hooks?: Hooks;
28
+ fetchHandler?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
29
+ }
30
+ interface FFetchOptions<TPlugins extends readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[] = readonly ClientPlugin<PluginExtensionBase, PluginRequestPromiseExtensionBase>[]> extends CoreClientOptions {
31
+ plugins?: TPlugins;
32
+ }
33
+ type FFetchRequestOptions = CoreClientOptions;
34
+ type FFetchRequestPromise<TRequestPromiseExtensions extends object = Record<never, never>> = Promise<Response> & TRequestPromiseExtensions;
35
+ type FFetch<TExtensions extends object = Record<never, never>, TRequestPromiseExtensions extends object = Record<never, never>> = {
36
+ (input: RequestInfo | URL, init?: FFetchRequestInit): FFetchRequestPromise<TRequestPromiseExtensions>;
37
+ pendingRequests: PendingRequest[];
38
+ abortAll: () => void;
39
+ } & TExtensions;
40
+ interface FFetchRequestInit extends RequestInit, FFetchRequestOptions {
41
+ }
42
+ type PendingRequest = {
43
+ promise: Promise<Response>;
44
+ request: Request;
45
+ controller: AbortController;
46
+ };
47
+
48
+ export type { FFetchOptions as F, Hooks as H, FFetch as a, FFetchRequestInit as b };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fetchkit/ffetch",
3
- "version": "5.0.1",
3
+ "version": "5.1.0",
4
4
  "description": "Fetch wrapper with configurable timeouts, retries, and TypeScript-first DX",
5
5
  "keywords": [
6
6
  "fetch",
@@ -36,6 +36,16 @@
36
36
  "types": "./dist/plugins/circuit.d.ts",
37
37
  "import": "./dist/plugins/circuit.js",
38
38
  "require": "./dist/plugins/circuit.cjs"
39
+ },
40
+ "./plugins/response-shortcuts": {
41
+ "types": "./dist/plugins/response-shortcuts.d.ts",
42
+ "import": "./dist/plugins/response-shortcuts.js",
43
+ "require": "./dist/plugins/response-shortcuts.cjs"
44
+ },
45
+ "./plugins/request-shortcuts": {
46
+ "types": "./dist/plugins/request-shortcuts.d.ts",
47
+ "import": "./dist/plugins/request-shortcuts.js",
48
+ "require": "./dist/plugins/request-shortcuts.cjs"
39
49
  }
40
50
  },
41
51
  "files": [