@zap-studio/fetch 0.1.1 → 0.1.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @zap-studio/fetch
2
2
 
3
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 69c2b21: Change `safeFetch` to `$fetch` syntax and make sure `safeFetch` can also be used for legacy
8
+
3
9
  ## 0.1.1
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -84,12 +84,12 @@ const deleted = await api.delete("/api/users/1", UserSchema);
84
84
 
85
85
  ## Advanced Usage
86
86
 
87
- ### Using `safeFetch` directly
87
+ ### Using `$fetch` directly
88
88
 
89
89
  ```typescript
90
- import { safeFetch } from "@zap-studio/fetch";
90
+ import { $fetch } from "@zap-studio/fetch";
91
91
 
92
- const result = await safeFetch(
92
+ const result = await $fetch(
93
93
  "https://api.example.com/users/1",
94
94
  UserSchema,
95
95
  {
@@ -105,14 +105,14 @@ const result = await safeFetch(
105
105
 
106
106
  ```typescript
107
107
  // Get text response
108
- const text = await safeFetch(
108
+ const text = await $fetch(
109
109
  "/api/data",
110
110
  z.string(),
111
111
  { responseType: "text" }
112
112
  );
113
113
 
114
114
  // Get blob response
115
- const blob = await safeFetch(
115
+ const blob = await $fetch(
116
116
  "/api/file",
117
117
  z.instanceof(Blob),
118
118
  { responseType: "blob" }
@@ -137,12 +137,12 @@ try {
137
137
 
138
138
  ```typescript
139
139
  // Throw on validation error (default)
140
- const user = await safeFetch(url, UserSchema, {
140
+ const user = await $fetch(url, UserSchema, {
141
141
  throwOnValidationError: true,
142
142
  });
143
143
 
144
144
  // Return validation result without throwing
145
- const result = await safeFetch(url, UserSchema, {
145
+ const result = await $fetch(url, UserSchema, {
146
146
  throwOnValidationError: false,
147
147
  });
148
148
 
@@ -7,4 +7,4 @@ declare class FetchError extends Error {
7
7
  }
8
8
  //#endregion
9
9
  export { FetchError };
10
- //# sourceMappingURL=index.d.ts.map
10
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/errors/index.ts"],"sourcesContent":[],"mappings":";cAAa,UAAA,SAAmB,KAAA;EAAnB,MAAA,EAAA,MAAW;EAGZ,UAAA,EAAA,MAAA;EAME,QAAA,EANF,QAME;EATkB,WAAA,CAAA,OAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EASlB,QATkB"}
@@ -0,0 +1,3 @@
1
+ import { t as FetchError } from "../errors-BCMOymYz.mjs";
2
+
3
+ export { FetchError };
@@ -1,14 +1,17 @@
1
1
  //#region src/errors/index.ts
2
2
  var FetchError = class extends Error {
3
+ status;
4
+ statusText;
5
+ response;
3
6
  constructor(message, status, statusText, response) {
4
7
  super(message);
8
+ this.name = "FetchError";
5
9
  this.status = status;
6
10
  this.statusText = statusText;
7
11
  this.response = response;
8
- this.name = "FetchError";
9
12
  }
10
13
  };
11
14
 
12
15
  //#endregion
13
16
  export { FetchError as t };
14
- //# sourceMappingURL=errors-DrfSty0J.js.map
17
+ //# sourceMappingURL=errors-BCMOymYz.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors-BCMOymYz.mjs","names":[],"sources":["../src/errors/index.ts"],"sourcesContent":["export class FetchError extends Error {\n status: number;\n statusText: string;\n response: Response;\n\n constructor(\n message: string,\n status: number,\n statusText: string,\n response: Response\n ) {\n super(message);\n this.name = \"FetchError\";\n this.status = status;\n this.statusText = statusText;\n this.response = response;\n }\n}\n"],"mappings":";AAAA,IAAa,aAAb,cAAgC,MAAM;CACpC;CACA;CACA;CAEA,YACE,SACA,QACA,YACA,UACA;AACA,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,SAAS;AACd,OAAK,aAAa;AAClB,OAAK,WAAW"}
@@ -0,0 +1,18 @@
1
+ //#region src/types/index.d.ts
2
+ type FetchConfig<TBody> = Omit<RequestInit, "body"> & {
3
+ body?: TBody;
4
+ throwOnValidationError?: boolean;
5
+ };
6
+ type ResponseType = "arrayBuffer" | "blob" | "bytes" | "clone" | "formData" | "json" | "text";
7
+ type ResponseTypeMap = {
8
+ arrayBuffer: ArrayBuffer;
9
+ blob: Blob;
10
+ bytes: Uint8Array;
11
+ clone: Response;
12
+ formData: FormData;
13
+ json: unknown;
14
+ text: string;
15
+ };
16
+ //#endregion
17
+ export { ResponseType as n, ResponseTypeMap as r, FetchConfig as t };
18
+ //# sourceMappingURL=index-Dz58_HD6.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Dz58_HD6.d.mts","names":[],"sources":["../src/types/index.ts"],"sourcesContent":[],"mappings":";KAAY,qBAAqB,KAAK;EAA1B,IAAA,CAAA,EACH,KADG;EAA0B,sBAAA,CAAA,EAAA,OAAA;CAAL;AACxB,KAIG,YAAA,GAJH,aAAA,GAAA,MAAA,GAAA,OAAA,GAAA,OAAA,GAAA,UAAA,GAAA,MAAA,GAAA,MAAA;AAAK,KAaF,eAAA,GAbE;EAIF,WAAA,EAUG,WAVS;EASZ,IAAA,EAEJ,IAFI;EACG,KAAA,EAEN,UAFM;EACP,KAAA,EAEC,QAFD;EACC,QAAA,EAEG,QAFH;EACA,IAAA,EAAA,OAAA;EACG,IAAA,EAAA,MAAA;CAAQ"}
@@ -0,0 +1,60 @@
1
+ import { n as ResponseType, t as FetchConfig } from "./index-Dz58_HD6.mjs";
2
+ import { z } from "zod";
3
+
4
+ //#region src/index.d.ts
5
+
6
+ /**
7
+ * Type-safe fetch wrapper with Zod validation
8
+ *
9
+ * @example
10
+ * import { z } from "zod";
11
+ * import { $fetch } from "@zap-studio/fetch";
12
+ *
13
+ * const UserSchema = z.object({
14
+ * id: z.number(),
15
+ * name: z.string(),
16
+ * email: z.string().email(),
17
+ * });
18
+ *
19
+ * async function getUser(userId: number) {
20
+ * const user = await $fetch(
21
+ * `https://api.example.com/users/${userId}`,
22
+ * UserSchema,
23
+ * { method: "GET" }
24
+ * );
25
+ * return user; // user is typed as { id: number; name: string; email: string; }
26
+ * }
27
+ */
28
+ declare function $fetch<TResponse, TBody = unknown, TResponseType extends ResponseType = "json">(resource: string, responseSchema: z.ZodType<TResponse>, config?: FetchConfig<TBody> & {
29
+ throwOnValidationError?: boolean;
30
+ responseType?: TResponseType;
31
+ }): Promise<TResponse | z.ZodSafeParseSuccess<TResponse> | z.ZodSafeParseError<TResponse>>;
32
+ declare const safeFetch: typeof $fetch;
33
+ /**
34
+ * Convenience methods for common HTTP verbs
35
+ *
36
+ * @example
37
+ * import { z } from "zod";
38
+ * import { api } from "@zap-studio/fetch";
39
+ *
40
+ * const PostSchema = z.object({
41
+ * id: z.number(),
42
+ * title: z.string(),
43
+ * content: z.string(),
44
+ * });
45
+ *
46
+ * async function fetchPost(postId: number) {
47
+ * const post = await api.get(`https://api.example.com/posts/${postId}`, PostSchema);
48
+ * return post; // post is typed as { id: number; title: string; content: string; }
49
+ * }
50
+ */
51
+ declare const api: {
52
+ get: <TResponse>(resource: string, schema: z.ZodType<TResponse>, options?: Omit<RequestInit, "method" | "body">) => Promise<TResponse | z.ZodSafeParseSuccess<TResponse> | z.ZodSafeParseError<TResponse>>;
53
+ post: <TResponse, TBody = unknown>(resource: string, schema: z.ZodType<TResponse>, body?: TBody, options?: Omit<RequestInit, "method" | "body">) => Promise<TResponse | z.ZodSafeParseSuccess<TResponse> | z.ZodSafeParseError<TResponse>>;
54
+ put: <TResponse, TBody = unknown>(resource: string, schema: z.ZodType<TResponse>, body?: TBody, options?: Omit<RequestInit, "method" | "body">) => Promise<TResponse | z.ZodSafeParseSuccess<TResponse> | z.ZodSafeParseError<TResponse>>;
55
+ patch: <TResponse, TBody = unknown>(resource: string, schema: z.ZodType<TResponse>, body?: TBody, options?: Omit<RequestInit, "method" | "body">) => Promise<TResponse | z.ZodSafeParseSuccess<TResponse> | z.ZodSafeParseError<TResponse>>;
56
+ delete: <TResponse>(resource: string, schema: z.ZodType<TResponse>, options?: Omit<RequestInit, "method" | "body">) => Promise<TResponse | z.ZodSafeParseSuccess<TResponse> | z.ZodSafeParseError<TResponse>>;
57
+ };
58
+ //#endregion
59
+ export { $fetch, api, safeFetch };
60
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;AA2BA;;;;;;;;;;;;;;AA+CA;AAoBA;;;;;AAIkD,iBAvE5B,MAuE4B,CAAA,SAAA,EAAA,QAAA,OAAA,EAAA,sBApE1B,YAoE0B,GAAA,MAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,cAAA,EAjEhC,CAAA,CAAE,OAiE8B,CAjEtB,SAiEsB,CAAA,EAAA,MAAA,CAAA,EAhEvC,WAgEuC,CAhE3B,KAgE2B,CAAA,GAAA;EAAA,sBAAA,CAAA,EAAA,OAAA;EAAA,YAAA,CAAA,EA9D/B,aA8D+B;CAAA,CAAA,EA5D/C,OA4D+C,CA3DhD,SA2DgD,GA3DpC,CAAA,CAAE,mBA2DkC,CA3Dd,SA2Dc,CAAA,GA3DD,CAAA,CAAE,iBA2DD,CA3DmB,SA2DnB,CAAA,CAAA;AAAA,cAxBrC,SAwBqC,EAAA,OAxB5B,MAwB4B;;;;;;;;;;;;;;;;;;;AAcA,cAlBrC,GAkBqC,EAAA;EAAA,GAAA,EAAA,CAAA,SAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,EAftC,CAAA,CAAE,OAeoC,CAf5B,SAe4B,CAAA,EAAA,OAAA,CAAA,EAdpC,IAcoC,CAd/B,WAc+B,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GAdA,OAcA,CAdA,SAcA,GAdA,CAAA,CAAA,mBAcA,CAdA,SAcA,CAAA,GAdA,CAAA,CAAA,iBAcA,CAdA,SAcA,CAAA,CAAA;EAAA,IAAA,EAAA,CAAA,SAAA,EAAA,QAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,EATtC,CAAA,CAAE,OASoC,CAT5B,SAS4B,CAAA,EAAA,IAAA,CAAA,EARvC,KAQuC,EAAA,OAAA,CAAA,EAPpC,IAOoC,CAP/B,WAO+B,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GAPA,OAOA,CAPA,SAOA,GAPA,CAAA,CAAA,mBAOA,CAPA,SAOA,CAAA,GAPA,CAAA,CAAA,iBAOA,CAPA,SAOA,CAAA,CAAA;EAAA,GAAA,EAAA,CAAA,SAAA,EAAA,QAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,EAFtC,CAAA,CAAE,OAEoC,CAF5B,SAE4B,CAAA,EAAA,IAAA,CAAA,EADvC,KACuC,EAAA,OAAA,CAAA,EAApC,IAAoC,CAA/B,WAA+B,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GAAA,OAAA,CAAA,SAAA,GAAA,CAAA,CAAA,mBAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,iBAAA,CAAA,SAAA,CAAA,CAAA;EAAA,KAAA,EAAA,CAAA,SAAA,EAAA,QAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,EAKtC,CAAA,CAAE,OALoC,CAK5B,SAL4B,CAAA,EAAA,IAAA,CAAA,EAMvC,KANuC,EAAA,OAAA,CAAA,EAOpC,IAPoC,CAO/B,WAP+B,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GAOA,OAPA,CAOA,SAPA,GAOA,CAAA,CAAA,mBAPA,CAOA,SAPA,CAAA,GAOA,CAAA,CAAA,iBAPA,CAOA,SAPA,CAAA,CAAA;EAK5B,MAAA,EAAA,CAAA,SAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,EAOV,CAAA,CAAE,OAPQ,CAOA,SAPA,CAAA,EAAA,OAAA,CAAA,EAQR,IARQ,CAQH,WARG,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GAQ4B,OAR5B,CAQ4B,SAR5B,GAQ4B,CAAA,CAAA,mBAR5B,CAQ4B,SAR5B,CAAA,GAQ4B,CAAA,CAAA,iBAR5B,CAQ4B,SAR5B,CAAA,CAAA;CAAV"}
package/dist/index.mjs ADDED
@@ -0,0 +1,86 @@
1
+ import { t as FetchError } from "./errors-BCMOymYz.mjs";
2
+ import { n as prepareHeadersAndBody, t as parseResponse } from "./utils-CZ-1Z2-1.mjs";
3
+
4
+ //#region src/index.ts
5
+ /**
6
+ * Type-safe fetch wrapper with Zod validation
7
+ *
8
+ * @example
9
+ * import { z } from "zod";
10
+ * import { $fetch } from "@zap-studio/fetch";
11
+ *
12
+ * const UserSchema = z.object({
13
+ * id: z.number(),
14
+ * name: z.string(),
15
+ * email: z.string().email(),
16
+ * });
17
+ *
18
+ * async function getUser(userId: number) {
19
+ * const user = await $fetch(
20
+ * `https://api.example.com/users/${userId}`,
21
+ * UserSchema,
22
+ * { method: "GET" }
23
+ * );
24
+ * return user; // user is typed as { id: number; name: string; email: string; }
25
+ * }
26
+ */
27
+ async function $fetch(resource, responseSchema, config) {
28
+ const { body, headers, throwOnValidationError = true, responseType = "json", ...rest } = config || {};
29
+ const { body: preparedBody, headers: preparedHeaders } = prepareHeadersAndBody(body, headers);
30
+ const response = await fetch(resource, {
31
+ ...rest,
32
+ body: preparedBody,
33
+ headers: preparedHeaders
34
+ });
35
+ if (!response.ok) throw new FetchError(`HTTP ${response.status}: ${response.statusText}`, response.status, response.statusText, response);
36
+ const data = await parseResponse(response, responseType);
37
+ return throwOnValidationError ? responseSchema.parse(data) : responseSchema.safeParse(data);
38
+ }
39
+ const safeFetch = $fetch;
40
+ /**
41
+ * Convenience methods for common HTTP verbs
42
+ *
43
+ * @example
44
+ * import { z } from "zod";
45
+ * import { api } from "@zap-studio/fetch";
46
+ *
47
+ * const PostSchema = z.object({
48
+ * id: z.number(),
49
+ * title: z.string(),
50
+ * content: z.string(),
51
+ * });
52
+ *
53
+ * async function fetchPost(postId: number) {
54
+ * const post = await api.get(`https://api.example.com/posts/${postId}`, PostSchema);
55
+ * return post; // post is typed as { id: number; title: string; content: string; }
56
+ * }
57
+ */
58
+ const api = {
59
+ get: (resource, schema, options) => $fetch(resource, schema, {
60
+ ...options,
61
+ method: "GET"
62
+ }),
63
+ post: (resource, schema, body, options) => $fetch(resource, schema, {
64
+ ...options,
65
+ method: "POST",
66
+ body
67
+ }),
68
+ put: (resource, schema, body, options) => $fetch(resource, schema, {
69
+ ...options,
70
+ method: "PUT",
71
+ body
72
+ }),
73
+ patch: (resource, schema, body, options) => $fetch(resource, schema, {
74
+ ...options,
75
+ method: "PATCH",
76
+ body
77
+ }),
78
+ delete: (resource, schema, options) => $fetch(resource, schema, {
79
+ ...options,
80
+ method: "DELETE"
81
+ })
82
+ };
83
+
84
+ //#endregion
85
+ export { $fetch, api, safeFetch };
86
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { z } from \"zod\";\nimport { FetchError } from \"./errors\";\nimport type { FetchConfig, ResponseType } from \"./types\";\nimport { parseResponse, prepareHeadersAndBody } from \"./utils\";\n\n/**\n * Type-safe fetch wrapper with Zod validation\n *\n * @example\n * import { z } from \"zod\";\n * import { $fetch } from \"@zap-studio/fetch\";\n *\n * const UserSchema = z.object({\n * id: z.number(),\n * name: z.string(),\n * email: z.string().email(),\n * });\n *\n * async function getUser(userId: number) {\n * const user = await $fetch(\n * `https://api.example.com/users/${userId}`,\n * UserSchema,\n * { method: \"GET\" }\n * );\n * return user; // user is typed as { id: number; name: string; email: string; }\n * }\n */\nexport async function $fetch<\n TResponse,\n TBody = unknown,\n TResponseType extends ResponseType = \"json\",\n>(\n resource: string,\n responseSchema: z.ZodType<TResponse>,\n config?: FetchConfig<TBody> & {\n throwOnValidationError?: boolean;\n responseType?: TResponseType;\n }\n): Promise<\n TResponse | z.ZodSafeParseSuccess<TResponse> | z.ZodSafeParseError<TResponse>\n> {\n const {\n body,\n headers,\n throwOnValidationError = true,\n responseType = \"json\" as TResponseType,\n ...rest\n } = config || {};\n\n const { body: preparedBody, headers: preparedHeaders } =\n prepareHeadersAndBody(body, headers);\n\n const response = await fetch(resource, {\n ...rest,\n body: preparedBody,\n headers: preparedHeaders,\n });\n\n if (!response.ok) {\n throw new FetchError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n response.statusText,\n response\n );\n }\n\n const data = await parseResponse(response, responseType);\n\n return throwOnValidationError\n ? responseSchema.parse(data)\n : responseSchema.safeParse(data);\n}\n\nexport const safeFetch = $fetch;\n\n/**\n * Convenience methods for common HTTP verbs\n *\n * @example\n * import { z } from \"zod\";\n * import { api } from \"@zap-studio/fetch\";\n *\n * const PostSchema = z.object({\n * id: z.number(),\n * title: z.string(),\n * content: z.string(),\n * });\n *\n * async function fetchPost(postId: number) {\n * const post = await api.get(`https://api.example.com/posts/${postId}`, PostSchema);\n * return post; // post is typed as { id: number; title: string; content: string; }\n * }\n */\nexport const api = {\n get: <TResponse>(\n resource: string,\n schema: z.ZodType<TResponse>,\n options?: Omit<RequestInit, \"method\" | \"body\">\n ) => $fetch(resource, schema, { ...options, method: \"GET\" }),\n\n post: <TResponse, TBody = unknown>(\n resource: string,\n schema: z.ZodType<TResponse>,\n body?: TBody,\n options?: Omit<RequestInit, \"method\" | \"body\">\n ) => $fetch(resource, schema, { ...options, method: \"POST\", body }),\n\n put: <TResponse, TBody = unknown>(\n resource: string,\n schema: z.ZodType<TResponse>,\n body?: TBody,\n options?: Omit<RequestInit, \"method\" | \"body\">\n ) => $fetch(resource, schema, { ...options, method: \"PUT\", body }),\n\n patch: <TResponse, TBody = unknown>(\n resource: string,\n schema: z.ZodType<TResponse>,\n body?: TBody,\n options?: Omit<RequestInit, \"method\" | \"body\">\n ) => $fetch(resource, schema, { ...options, method: \"PATCH\", body }),\n\n delete: <TResponse>(\n resource: string,\n schema: z.ZodType<TResponse>,\n options?: Omit<RequestInit, \"method\" | \"body\">\n ) => $fetch(resource, schema, { ...options, method: \"DELETE\" }),\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,eAAsB,OAKpB,UACA,gBACA,QAMA;CACA,MAAM,EACJ,MACA,SACA,yBAAyB,MACzB,eAAe,QACf,GAAG,SACD,UAAU,EAAE;CAEhB,MAAM,EAAE,MAAM,cAAc,SAAS,oBACnC,sBAAsB,MAAM,QAAQ;CAEtC,MAAM,WAAW,MAAM,MAAM,UAAU;EACrC,GAAG;EACH,MAAM;EACN,SAAS;EACV,CAAC;AAEF,KAAI,CAAC,SAAS,GACZ,OAAM,IAAI,WACR,QAAQ,SAAS,OAAO,IAAI,SAAS,cACrC,SAAS,QACT,SAAS,YACT,SACD;CAGH,MAAM,OAAO,MAAM,cAAc,UAAU,aAAa;AAExD,QAAO,yBACH,eAAe,MAAM,KAAK,GAC1B,eAAe,UAAU,KAAK;;AAGpC,MAAa,YAAY;;;;;;;;;;;;;;;;;;;AAoBzB,MAAa,MAAM;CACjB,MACE,UACA,QACA,YACG,OAAO,UAAU,QAAQ;EAAE,GAAG;EAAS,QAAQ;EAAO,CAAC;CAE5D,OACE,UACA,QACA,MACA,YACG,OAAO,UAAU,QAAQ;EAAE,GAAG;EAAS,QAAQ;EAAQ;EAAM,CAAC;CAEnE,MACE,UACA,QACA,MACA,YACG,OAAO,UAAU,QAAQ;EAAE,GAAG;EAAS,QAAQ;EAAO;EAAM,CAAC;CAElE,QACE,UACA,QACA,MACA,YACG,OAAO,UAAU,QAAQ;EAAE,GAAG;EAAS,QAAQ;EAAS;EAAM,CAAC;CAEpE,SACE,UACA,QACA,YACG,OAAO,UAAU,QAAQ;EAAE,GAAG;EAAS,QAAQ;EAAU,CAAC;CAChE"}
@@ -0,0 +1,2 @@
1
+ import { n as ResponseType, r as ResponseTypeMap, t as FetchConfig } from "../index-Dz58_HD6.mjs";
2
+ export { FetchConfig, ResponseType, ResponseTypeMap };
@@ -0,0 +1,11 @@
1
+ import { n as ResponseType, r as ResponseTypeMap } from "../index-Dz58_HD6.mjs";
2
+
3
+ //#region src/utils/index.d.ts
4
+ declare function parseResponse<TResponseType extends ResponseType>(response: Response, responseType: TResponseType): Promise<ResponseTypeMap[TResponseType]>;
5
+ declare function prepareHeadersAndBody<TBody = unknown>(body: TBody, headers: HeadersInit | undefined): {
6
+ body: BodyInit | null;
7
+ headers: HeadersInit | undefined;
8
+ };
9
+ //#endregion
10
+ export { parseResponse, prepareHeadersAndBody };
11
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/utils/index.ts"],"sourcesContent":[],"mappings":";;;iBAGgB,oCAAoC,wBACxC,wBACI,gBACb,QAAQ,gBAAgB;iBAmEX,6CACR,gBACG;EAxEK,IAAA,EAyEL,QAzEK,GAAa,IAAA;EAAuB,OAAA,EAyEf,WAzEe,GAAA,SAAA;CACxC"}
@@ -0,0 +1,4 @@
1
+ import "../errors-BCMOymYz.mjs";
2
+ import { n as prepareHeadersAndBody, t as parseResponse } from "../utils-CZ-1Z2-1.mjs";
3
+
4
+ export { parseResponse, prepareHeadersAndBody };
@@ -0,0 +1,53 @@
1
+ import { t as FetchError } from "./errors-BCMOymYz.mjs";
2
+
3
+ //#region src/utils/index.ts
4
+ function parseResponse(response, responseType) {
5
+ const contentType = response.headers.get("content-type");
6
+ const parser = {
7
+ json: async () => {
8
+ if (!contentType?.includes("application/json")) throw new FetchError(contentType ? `Expected JSON response but received content type: ${contentType}` : "Expected JSON response but received no content type", response.status, response.statusText, response);
9
+ return await response.json();
10
+ },
11
+ arrayBuffer: async () => response.arrayBuffer(),
12
+ blob: async () => response.blob(),
13
+ bytes: async () => {
14
+ const buffer = await response.arrayBuffer();
15
+ return new Uint8Array(buffer);
16
+ },
17
+ clone: async () => response.clone(),
18
+ formData: async () => {
19
+ if (!contentType?.includes("multipart/form-data")) throw new FetchError("Expected FormData response but received different content type", response.status, response.statusText, response);
20
+ return await response.formData();
21
+ },
22
+ text: async () => {
23
+ if (!contentType?.includes("text/")) throw new FetchError("Expected text response but received different content type", response.status, response.statusText, response);
24
+ return await response.text();
25
+ }
26
+ }[responseType];
27
+ if (!parser) return Promise.reject(new FetchError(`Unsupported response type: ${responseType}`, response.status, response.statusText, response));
28
+ return parser();
29
+ }
30
+ function prepareHeadersAndBody(body, headers) {
31
+ let preparedBody = null;
32
+ let preparedHeaders = headers;
33
+ if (body === null || body === void 0) return {
34
+ body: null,
35
+ headers: preparedHeaders
36
+ };
37
+ if (body instanceof FormData || body instanceof URLSearchParams || body instanceof Blob || body instanceof ArrayBuffer || body instanceof ReadableStream || typeof body === "string") preparedBody = body;
38
+ else if (typeof body === "object") {
39
+ preparedBody = JSON.stringify(body);
40
+ preparedHeaders = {
41
+ "Content-Type": "application/json",
42
+ ...headers
43
+ };
44
+ } else preparedBody = String(body);
45
+ return {
46
+ body: preparedBody,
47
+ headers: preparedHeaders
48
+ };
49
+ }
50
+
51
+ //#endregion
52
+ export { prepareHeadersAndBody as n, parseResponse as t };
53
+ //# sourceMappingURL=utils-CZ-1Z2-1.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-CZ-1Z2-1.mjs","names":["preparedBody: BodyInit | null"],"sources":["../src/utils/index.ts"],"sourcesContent":["import { FetchError } from \"../errors\";\nimport type { ResponseType, ResponseTypeMap } from \"../types\";\n\nexport function parseResponse<TResponseType extends ResponseType>(\n response: Response,\n responseType: TResponseType\n): Promise<ResponseTypeMap[TResponseType]> {\n const contentType = response.headers.get(\"content-type\");\n\n const parsers: Record<\n ResponseType,\n () => Promise<ResponseTypeMap[ResponseType]>\n > = {\n json: async () => {\n if (!contentType?.includes(\"application/json\")) {\n const errorMessage = contentType\n ? `Expected JSON response but received content type: ${contentType}`\n : \"Expected JSON response but received no content type\";\n throw new FetchError(\n errorMessage,\n response.status,\n response.statusText,\n response\n );\n }\n return await response.json();\n },\n arrayBuffer: async () => response.arrayBuffer(),\n blob: async () => response.blob(),\n bytes: async () => {\n const buffer = await response.arrayBuffer();\n return new Uint8Array(buffer);\n },\n clone: async () => response.clone(),\n formData: async () => {\n if (!contentType?.includes(\"multipart/form-data\")) {\n throw new FetchError(\n \"Expected FormData response but received different content type\",\n response.status,\n response.statusText,\n response\n );\n }\n return await response.formData();\n },\n text: async () => {\n if (!contentType?.includes(\"text/\")) {\n throw new FetchError(\n \"Expected text response but received different content type\",\n response.status,\n response.statusText,\n response\n );\n }\n return await response.text();\n },\n };\n\n const parser = parsers[responseType];\n if (!parser) {\n return Promise.reject(\n new FetchError(\n `Unsupported response type: ${responseType}`,\n response.status,\n response.statusText,\n response\n )\n ) as Promise<ResponseTypeMap[TResponseType]>;\n }\n\n return parser() as Promise<ResponseTypeMap[TResponseType]>;\n}\n\nexport function prepareHeadersAndBody<TBody = unknown>(\n body: TBody,\n headers: HeadersInit | undefined\n): { body: BodyInit | null; headers: HeadersInit | undefined } {\n let preparedBody: BodyInit | null = null;\n let preparedHeaders = headers;\n\n // Handle null/undefined body\n if (body === null || body === undefined) {\n return { body: null, headers: preparedHeaders };\n }\n\n // Check if body is already a valid BodyInit type\n if (\n body instanceof FormData ||\n body instanceof URLSearchParams ||\n body instanceof Blob ||\n body instanceof ArrayBuffer ||\n body instanceof ReadableStream ||\n typeof body === \"string\"\n ) {\n preparedBody = body as BodyInit;\n } else if (typeof body === \"object\") {\n // If body is a plain object, stringify it and set Content-Type\n preparedBody = JSON.stringify(body);\n preparedHeaders = {\n \"Content-Type\": \"application/json\",\n ...headers,\n };\n } else {\n // Handle other primitive types by converting to string\n preparedBody = String(body);\n }\n\n return { body: preparedBody, headers: preparedHeaders };\n}\n"],"mappings":";;;AAGA,SAAgB,cACd,UACA,cACyC;CACzC,MAAM,cAAc,SAAS,QAAQ,IAAI,eAAe;CAmDxD,MAAM,SA9CF;EACF,MAAM,YAAY;AAChB,OAAI,CAAC,aAAa,SAAS,mBAAmB,CAI5C,OAAM,IAAI,WAHW,cACjB,qDAAqD,gBACrD,uDAGF,SAAS,QACT,SAAS,YACT,SACD;AAEH,UAAO,MAAM,SAAS,MAAM;;EAE9B,aAAa,YAAY,SAAS,aAAa;EAC/C,MAAM,YAAY,SAAS,MAAM;EACjC,OAAO,YAAY;GACjB,MAAM,SAAS,MAAM,SAAS,aAAa;AAC3C,UAAO,IAAI,WAAW,OAAO;;EAE/B,OAAO,YAAY,SAAS,OAAO;EACnC,UAAU,YAAY;AACpB,OAAI,CAAC,aAAa,SAAS,sBAAsB,CAC/C,OAAM,IAAI,WACR,kEACA,SAAS,QACT,SAAS,YACT,SACD;AAEH,UAAO,MAAM,SAAS,UAAU;;EAElC,MAAM,YAAY;AAChB,OAAI,CAAC,aAAa,SAAS,QAAQ,CACjC,OAAM,IAAI,WACR,8DACA,SAAS,QACT,SAAS,YACT,SACD;AAEH,UAAO,MAAM,SAAS,MAAM;;EAE/B,CAEsB;AACvB,KAAI,CAAC,OACH,QAAO,QAAQ,OACb,IAAI,WACF,8BAA8B,gBAC9B,SAAS,QACT,SAAS,YACT,SACD,CACF;AAGH,QAAO,QAAQ;;AAGjB,SAAgB,sBACd,MACA,SAC6D;CAC7D,IAAIA,eAAgC;CACpC,IAAI,kBAAkB;AAGtB,KAAI,SAAS,QAAQ,SAAS,OAC5B,QAAO;EAAE,MAAM;EAAM,SAAS;EAAiB;AAIjD,KACE,gBAAgB,YAChB,gBAAgB,mBAChB,gBAAgB,QAChB,gBAAgB,eAChB,gBAAgB,kBAChB,OAAO,SAAS,SAEhB,gBAAe;UACN,OAAO,SAAS,UAAU;AAEnC,iBAAe,KAAK,UAAU,KAAK;AACnC,oBAAkB;GAChB,gBAAgB;GAChB,GAAG;GACJ;OAGD,gBAAe,OAAO,KAAK;AAG7B,QAAO;EAAE,MAAM;EAAc,SAAS;EAAiB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zap-studio/fetch",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -16,23 +16,25 @@
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/node": "latest",
19
+ "@vitest/coverage-v8": "^4.0.13",
19
20
  "jsdom": "latest",
20
21
  "tsdown": "latest",
21
22
  "typescript": "latest",
22
23
  "vitest": "latest",
23
24
  "@zap-studio/tsdown-config": "0.0.0",
24
- "@zap-studio/vitest-config": "0.0.0",
25
- "@zap-studio/typescript-config": "0.0.0"
25
+ "@zap-studio/typescript-config": "0.0.0",
26
+ "@zap-studio/vitest-config": "0.0.0"
26
27
  },
27
28
  "exports": {
28
- ".": "./dist/index.js",
29
- "./errors": "./dist/errors/index.js",
30
- "./types": "./dist/types/index.js",
29
+ ".": "./dist/index.mjs",
30
+ "./errors": "./dist/errors/index.mjs",
31
+ "./types": "./dist/types/index.mjs",
32
+ "./utils": "./dist/utils/index.mjs",
31
33
  "./package.json": "./package.json"
32
34
  },
33
- "main": "./dist/index.js",
34
- "module": "./dist/index.js",
35
- "types": "./dist/index.d.ts",
35
+ "main": "./dist/index.mjs",
36
+ "module": "./dist/index.mjs",
37
+ "types": "./dist/index.d.mts",
36
38
  "scripts": {
37
39
  "build": "tsdown --config tsdown.config.ts",
38
40
  "check-types": "tsc --noEmit",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/errors/index.ts"],"sourcesContent":[],"mappings":";cAAa,UAAA,SAAmB,KAAA;EAAnB,MAAA,EAAA,MAAW;EAKL,UAAA,EAAA,MAAA;EAAA,QAAA,EAAA,QAAA;EALa,WAAA,CAAA,OAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAKb,QALa"}
@@ -1,3 +0,0 @@
1
- import { t as FetchError } from "../errors-DrfSty0J.js";
2
-
3
- export { FetchError };
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors-DrfSty0J.js","names":["status: number","statusText: string","response: Response"],"sources":["../src/errors/index.ts"],"sourcesContent":["export class FetchError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic status: number,\n\t\tpublic statusText: string,\n\t\tpublic response: Response,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"FetchError\";\n\t}\n}\n"],"mappings":";AAAA,IAAa,aAAb,cAAgC,MAAM;CACrC,YACC,SACA,AAAOA,QACP,AAAOC,YACP,AAAOC,UACN;AACD,QAAM,QAAQ;EAJP;EACA;EACA;AAGP,OAAK,OAAO"}
@@ -1,9 +0,0 @@
1
- //#region src/types/index.d.ts
2
- type FetchConfig<TBody> = Omit<RequestInit, "body"> & {
3
- body?: TBody;
4
- throwOnValidationError?: boolean;
5
- };
6
- type ResponseType = "json" | "text" | "blob" | "arrayBuffer" | "formData";
7
- //#endregion
8
- export { ResponseType as n, FetchConfig as t };
9
- //# sourceMappingURL=index-BkzLFXkF.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BkzLFXkF.d.ts","names":[],"sources":["../src/types/index.ts"],"sourcesContent":[],"mappings":";KAAY,qBAAqB,KAAK;EAA1B,IAAA,CAAA,EACJ,KADI;EAA0B,sBAAA,CAAA,EAAA,OAAA;CAAL;AACzB,KAII,YAAA,GAJJ,MAAA,GAAA,MAAA,GAAA,MAAA,GAAA,aAAA,GAAA,UAAA"}
package/dist/index.d.ts DELETED
@@ -1,63 +0,0 @@
1
- import { n as ResponseType, t as FetchConfig } from "./index-BkzLFXkF.js";
2
- import { z } from "zod";
3
-
4
- //#region src/index.d.ts
5
-
6
- /**
7
- * Type-safe fetch wrapper with Zod validation
8
- *
9
- * @example
10
- * import { z } from "zod";
11
- * import { safeFetch } from "@zap-studio/fetch";
12
- *
13
- * const UserSchema = z.object({
14
- * id: z.number(),
15
- * name: z.string(),
16
- * email: z.string().email(),
17
- * });
18
- *
19
- * async function getUser(userId: number) {
20
- * const user = await safeFetch(
21
- * `https://api.example.com/users/${userId}`,
22
- * UserSchema,
23
- * { method: "GET" }
24
- * );
25
- * return user; // user is typed as { id: number; name: string; email: string; }
26
- * }
27
- */
28
- declare function safeFetch<TResponse$1, TBody$1 = unknown>(url: string, responseSchema: z.ZodType<TResponse$1>, config?: FetchConfig<TBody$1> & {
29
- throwOnValidationError?: true;
30
- responseType?: ResponseType;
31
- }): Promise<TResponse$1>;
32
- declare function safeFetch<TResponse$1, TBody$1 = unknown>(url: string, responseSchema: z.ZodType<TResponse$1>, config?: FetchConfig<TBody$1> & {
33
- throwOnValidationError: false;
34
- responseType?: ResponseType;
35
- }): Promise<ReturnType<typeof responseSchema.safeParse>>;
36
- /**
37
- * Convenience methods for common HTTP verbs
38
- *
39
- * @example
40
- * import { z } from "zod";
41
- * import { api } from "@zap-studio/fetch";
42
- *
43
- * const PostSchema = z.object({
44
- * id: z.number(),
45
- * title: z.string(),
46
- * content: z.string(),
47
- * });
48
- *
49
- * async function fetchPost(postId: number) {
50
- * const post = await api.get(`https://api.example.com/posts/${postId}`, PostSchema);
51
- * return post; // post is typed as { id: number; title: string; content: string; }
52
- * }
53
- */
54
- declare const api: {
55
- get: <TResponse>(url: string, schema: z.ZodType<TResponse>, config?: Omit<RequestInit, "method" | "body">) => Promise<TResponse>;
56
- post: <TResponse, TBody = unknown>(url: string, schema: z.ZodType<TResponse>, body?: TBody, config?: Omit<RequestInit, "method" | "body">) => Promise<TResponse>;
57
- put: <TResponse, TBody = unknown>(url: string, schema: z.ZodType<TResponse>, body?: TBody, config?: Omit<RequestInit, "method" | "body">) => Promise<TResponse>;
58
- patch: <TResponse, TBody = unknown>(url: string, schema: z.ZodType<TResponse>, body?: TBody, config?: Omit<RequestInit, "method" | "body">) => Promise<TResponse>;
59
- delete: <TResponse>(url: string, schema: z.ZodType<TResponse>, config?: Omit<RequestInit, "method" | "body">) => Promise<TResponse>;
60
- };
61
- //#endregion
62
- export { api, safeFetch };
63
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;AA0BA;;;;;;;;;AASA;;;;;;;;;;AAoHA;AAGoB,iBAhIE,SAgIF,CAAA,WAAA,EAAA,UAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,cAAA,EA9HH,CAAA,CAAE,OA8HC,CA9HO,WA8HP,CAAA,EAAA,MACT,CADS,EA7HV,WA6HU,CA7HE,OA6HF,CAAA,GAAA;EAAR,sBAAA,CAAA,EAAA,IAAA;EACI,YAAA,CAAA,EA5HC,YA4HD;CAAL,CAAA,EA1HR,OA0HQ,CA1HA,WA0HA,CAAA;AAAoC,iBAxHzB,SAwHyB,CAAA,WAAA,EAAA,UAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,cAAA,EAtH9B,CAAA,CAAE,OAsH4B,CAtHpB,WAsHoB,CAAA,EAAA,MAKrC,CALqC,EArHrC,WAqHqC,CArHzB,OAqHyB,CAAA,GAAA;EAAA,sBAAA,EAAA,KAAA;EAK3B,YAAA,CAAA,EAxHH,YAwHG;CAAV,CAAA,EAtHP,OAsHS,CAtHD,UAsHC,CAAA,OAtHiB,cAAA,CAAe,SAsHhC,CAAA,CAAA;;;;;;;;;;;;;;;;;;;AAgBmC,cAzBlC,GAyBkC,EAAA;EAK3B,GAAA,EAAA,CAAA,SAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,MAAA,EA3BV,CAAA,CAAE,OA2BQ,CA3BA,SA2BA,CAAA,EAAA,MAAA,CAAA,EA1BT,IA0BS,CA1BJ,WA0BI,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GA1B2B,OA0B3B,CA1B2B,SA0B3B,CAAA;EAAR,IAAA,EAAA,CAAA,SAAA,EAAA,QAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,MAAA,EArBF,CAAA,CAAE,OAqBA,CArBQ,SAqBR,CAAA,EAAA,IAAA,CAAA,EApBH,KAoBG,EAAA,MAAA,CAAA,EAnBD,IAmBC,CAnBI,WAmBJ,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GAnBmC,OAmBnC,CAnBmC,SAmBnC,CAAA;EACI,GAAA,EAAA,CAAA,SAAA,EAAA,QAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,MAAA,EAfN,CAAA,CAAE,OAeI,CAfI,SAeJ,CAAA,EAAA,IAAA,CAAA,EAdP,KAcO,EAAA,MAAA,CAAA,EAbL,IAaK,CAbA,WAaA,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GAb+B,OAa/B,CAb+B,SAa/B,CAAA;EAAL,KAAA,EAAA,CAAA,SAAA,EAAA,QAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,MAAA,EARD,CAAA,CAAE,OAQD,CARS,SAQT,CAAA,EAAA,IAAA,CAAA,EAPF,KAOE,EAAA,MAAA,CAAA,EANA,IAMA,CANK,WAML,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GANoC,OAMpC,CANoC,SAMpC,CAAA;EAAoC,MAAA,EAAA,CAAA,SAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,MAAA,EADrC,CAAA,CAAE,OACmC,CAD3B,SAC2B,CAAA,EAAA,MAAA,CAAA,EAApC,IAAoC,CAA/B,WAA+B,EAAA,QAAA,GAAA,MAAA,CAAA,EAAA,GAAA,OAAA,CAAA,SAAA,CAAA;CAAA"}
package/dist/index.js DELETED
@@ -1,79 +0,0 @@
1
- import { t as FetchError } from "./errors-DrfSty0J.js";
2
-
3
- //#region src/index.ts
4
- async function safeFetch(url, responseSchema, config) {
5
- const { body, headers, throwOnValidationError = true, responseType = "json",...rest } = config || {};
6
- const fetchConfig = {
7
- ...rest,
8
- headers: { ...headers }
9
- };
10
- if (body !== void 0) {
11
- const shouldSetContentType = !headers || typeof headers === "object" && !Array.isArray(headers) && !(headers instanceof Headers) && !("Content-Type" in headers);
12
- if (body instanceof FormData) fetchConfig.body = body;
13
- else if (typeof body === "string") {
14
- fetchConfig.body = body;
15
- if (shouldSetContentType) fetchConfig.headers["Content-Type"] = "text/plain";
16
- } else {
17
- fetchConfig.body = JSON.stringify(body);
18
- if (shouldSetContentType) fetchConfig.headers["Content-Type"] = "application/json";
19
- }
20
- }
21
- const response = await fetch(url, fetchConfig);
22
- if (!response.ok) throw new FetchError(`HTTP ${response.status}: ${response.statusText}`, response.status, response.statusText, response);
23
- let data;
24
- if (responseType === "json") if (response.headers.get("content-type")?.includes("application/json")) data = await response.json();
25
- else throw new FetchError("Expected JSON response but received different content type", response.status, response.statusText, response);
26
- else if (responseType === "text") data = await response.text();
27
- else if (responseType === "blob") data = await response.blob();
28
- else if (responseType === "arrayBuffer") data = await response.arrayBuffer();
29
- else if (responseType === "formData") data = await response.formData();
30
- if (throwOnValidationError) return responseSchema.parse(data);
31
- return responseSchema.safeParse(data);
32
- }
33
- /**
34
- * Convenience methods for common HTTP verbs
35
- *
36
- * @example
37
- * import { z } from "zod";
38
- * import { api } from "@zap-studio/fetch";
39
- *
40
- * const PostSchema = z.object({
41
- * id: z.number(),
42
- * title: z.string(),
43
- * content: z.string(),
44
- * });
45
- *
46
- * async function fetchPost(postId: number) {
47
- * const post = await api.get(`https://api.example.com/posts/${postId}`, PostSchema);
48
- * return post; // post is typed as { id: number; title: string; content: string; }
49
- * }
50
- */
51
- const api = {
52
- get: (url, schema, config) => safeFetch(url, schema, {
53
- ...config,
54
- method: "GET"
55
- }),
56
- post: (url, schema, body, config) => safeFetch(url, schema, {
57
- ...config,
58
- method: "POST",
59
- body
60
- }),
61
- put: (url, schema, body, config) => safeFetch(url, schema, {
62
- ...config,
63
- method: "PUT",
64
- body
65
- }),
66
- patch: (url, schema, body, config) => safeFetch(url, schema, {
67
- ...config,
68
- method: "PATCH",
69
- body
70
- }),
71
- delete: (url, schema, config) => safeFetch(url, schema, {
72
- ...config,
73
- method: "DELETE"
74
- })
75
- };
76
-
77
- //#endregion
78
- export { api, safeFetch };
79
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["fetchConfig: RequestInit","data: unknown"],"sources":["../src/index.ts"],"sourcesContent":["import type { z } from \"zod\";\nimport { FetchError } from \"./errors\";\nimport type { FetchConfig, ResponseType } from \"./types\";\n\n/**\n * Type-safe fetch wrapper with Zod validation\n *\n * @example\n * import { z } from \"zod\";\n * import { safeFetch } from \"@zap-studio/fetch\";\n *\n * const UserSchema = z.object({\n * id: z.number(),\n * name: z.string(),\n * email: z.string().email(),\n * });\n *\n * async function getUser(userId: number) {\n * const user = await safeFetch(\n * `https://api.example.com/users/${userId}`,\n * UserSchema,\n * { method: \"GET\" }\n * );\n * return user; // user is typed as { id: number; name: string; email: string; }\n * }\n */\nexport async function safeFetch<TResponse, TBody = unknown>(\n\turl: string,\n\tresponseSchema: z.ZodType<TResponse>,\n\tconfig?: FetchConfig<TBody> & {\n\t\tthrowOnValidationError?: true;\n\t\tresponseType?: ResponseType;\n\t},\n): Promise<TResponse>;\n\nexport async function safeFetch<TResponse, TBody = unknown>(\n\turl: string,\n\tresponseSchema: z.ZodType<TResponse>,\n\tconfig?: FetchConfig<TBody> & {\n\t\tthrowOnValidationError: false;\n\t\tresponseType?: ResponseType;\n\t},\n): Promise<ReturnType<typeof responseSchema.safeParse>>;\n\nexport async function safeFetch<TResponse, TBody = unknown>(\n\turl: string,\n\tresponseSchema: z.ZodType<TResponse>,\n\tconfig?: FetchConfig<TBody> & { responseType?: ResponseType },\n): Promise<TResponse | ReturnType<typeof responseSchema.safeParse>> {\n\tconst {\n\t\tbody,\n\t\theaders,\n\t\tthrowOnValidationError = true,\n\t\tresponseType = \"json\",\n\t\t...rest\n\t} = config || {};\n\n\tconst fetchConfig: RequestInit = {\n\t\t...rest,\n\t\theaders: {\n\t\t\t...(headers as Record<string, string>),\n\t\t},\n\t};\n\n\t// Only set Content-Type if body exists and it's not FormData\n\tif (body !== undefined) {\n\t\tconst shouldSetContentType =\n\t\t\t!headers ||\n\t\t\t(typeof headers === \"object\" &&\n\t\t\t\t!Array.isArray(headers) &&\n\t\t\t\t!(headers instanceof Headers) &&\n\t\t\t\t!(\"Content-Type\" in headers));\n\n\t\tif (body instanceof FormData) {\n\t\t\tfetchConfig.body = body;\n\t\t} else if (typeof body === \"string\") {\n\t\t\tfetchConfig.body = body;\n\t\t\tif (shouldSetContentType) {\n\t\t\t\t(fetchConfig.headers as Record<string, string>)[\"Content-Type\"] =\n\t\t\t\t\t\"text/plain\";\n\t\t\t}\n\t\t} else {\n\t\t\tfetchConfig.body = JSON.stringify(body);\n\t\t\tif (shouldSetContentType) {\n\t\t\t\t(fetchConfig.headers as Record<string, string>)[\"Content-Type\"] =\n\t\t\t\t\t\"application/json\";\n\t\t\t}\n\t\t}\n\t}\n\n\tconst response = await fetch(url, fetchConfig);\n\n\tif (!response.ok) {\n\t\tthrow new FetchError(\n\t\t\t`HTTP ${response.status}: ${response.statusText}`,\n\t\t\tresponse.status,\n\t\t\tresponse.statusText,\n\t\t\tresponse,\n\t\t);\n\t}\n\n\t// Parse response based on responseType\n\tlet data: unknown;\n\n\tif (responseType === \"json\") {\n\t\tconst contentType = response.headers.get(\"content-type\");\n\t\tif (contentType?.includes(\"application/json\")) {\n\t\t\tdata = await response.json();\n\t\t} else {\n\t\t\tthrow new FetchError(\n\t\t\t\t\"Expected JSON response but received different content type\",\n\t\t\t\tresponse.status,\n\t\t\t\tresponse.statusText,\n\t\t\t\tresponse,\n\t\t\t);\n\t\t}\n\t} else if (responseType === \"text\") {\n\t\tdata = await response.text();\n\t} else if (responseType === \"blob\") {\n\t\tdata = await response.blob();\n\t} else if (responseType === \"arrayBuffer\") {\n\t\tdata = await response.arrayBuffer();\n\t} else if (responseType === \"formData\") {\n\t\tdata = await response.formData();\n\t}\n\n\tif (throwOnValidationError) {\n\t\treturn responseSchema.parse(data);\n\t}\n\n\treturn responseSchema.safeParse(data);\n}\n\n/**\n * Convenience methods for common HTTP verbs\n *\n * @example\n * import { z } from \"zod\";\n * import { api } from \"@zap-studio/fetch\";\n *\n * const PostSchema = z.object({\n * id: z.number(),\n * title: z.string(),\n * content: z.string(),\n * });\n *\n * async function fetchPost(postId: number) {\n * const post = await api.get(`https://api.example.com/posts/${postId}`, PostSchema);\n * return post; // post is typed as { id: number; title: string; content: string; }\n * }\n */\nexport const api = {\n\tget: <TResponse>(\n\t\turl: string,\n\t\tschema: z.ZodType<TResponse>,\n\t\tconfig?: Omit<RequestInit, \"method\" | \"body\">,\n\t) => safeFetch(url, schema, { ...config, method: \"GET\" }),\n\n\tpost: <TResponse, TBody = unknown>(\n\t\turl: string,\n\t\tschema: z.ZodType<TResponse>,\n\t\tbody?: TBody,\n\t\tconfig?: Omit<RequestInit, \"method\" | \"body\">,\n\t) => safeFetch(url, schema, { ...config, method: \"POST\", body }),\n\n\tput: <TResponse, TBody = unknown>(\n\t\turl: string,\n\t\tschema: z.ZodType<TResponse>,\n\t\tbody?: TBody,\n\t\tconfig?: Omit<RequestInit, \"method\" | \"body\">,\n\t) => safeFetch(url, schema, { ...config, method: \"PUT\", body }),\n\n\tpatch: <TResponse, TBody = unknown>(\n\t\turl: string,\n\t\tschema: z.ZodType<TResponse>,\n\t\tbody?: TBody,\n\t\tconfig?: Omit<RequestInit, \"method\" | \"body\">,\n\t) => safeFetch(url, schema, { ...config, method: \"PATCH\", body }),\n\n\tdelete: <TResponse>(\n\t\turl: string,\n\t\tschema: z.ZodType<TResponse>,\n\t\tconfig?: Omit<RequestInit, \"method\" | \"body\">,\n\t) => safeFetch(url, schema, { ...config, method: \"DELETE\" }),\n};\n"],"mappings":";;;AA4CA,eAAsB,UACrB,KACA,gBACA,QACmE;CACnE,MAAM,EACL,MACA,SACA,yBAAyB,MACzB,eAAe,OACf,GAAG,SACA,UAAU,EAAE;CAEhB,MAAMA,cAA2B;EAChC,GAAG;EACH,SAAS,EACR,GAAI,SACJ;EACD;AAGD,KAAI,SAAS,QAAW;EACvB,MAAM,uBACL,CAAC,WACA,OAAO,YAAY,YACnB,CAAC,MAAM,QAAQ,QAAQ,IACvB,EAAE,mBAAmB,YACrB,EAAE,kBAAkB;AAEtB,MAAI,gBAAgB,SACnB,aAAY,OAAO;WACT,OAAO,SAAS,UAAU;AACpC,eAAY,OAAO;AACnB,OAAI,qBACH,CAAC,YAAY,QAAmC,kBAC/C;SAEI;AACN,eAAY,OAAO,KAAK,UAAU,KAAK;AACvC,OAAI,qBACH,CAAC,YAAY,QAAmC,kBAC/C;;;CAKJ,MAAM,WAAW,MAAM,MAAM,KAAK,YAAY;AAE9C,KAAI,CAAC,SAAS,GACb,OAAM,IAAI,WACT,QAAQ,SAAS,OAAO,IAAI,SAAS,cACrC,SAAS,QACT,SAAS,YACT,SACA;CAIF,IAAIC;AAEJ,KAAI,iBAAiB,OAEpB,KADoB,SAAS,QAAQ,IAAI,eAAe,EACvC,SAAS,mBAAmB,CAC5C,QAAO,MAAM,SAAS,MAAM;KAE5B,OAAM,IAAI,WACT,8DACA,SAAS,QACT,SAAS,YACT,SACA;UAEQ,iBAAiB,OAC3B,QAAO,MAAM,SAAS,MAAM;UAClB,iBAAiB,OAC3B,QAAO,MAAM,SAAS,MAAM;UAClB,iBAAiB,cAC3B,QAAO,MAAM,SAAS,aAAa;UACzB,iBAAiB,WAC3B,QAAO,MAAM,SAAS,UAAU;AAGjC,KAAI,uBACH,QAAO,eAAe,MAAM,KAAK;AAGlC,QAAO,eAAe,UAAU,KAAK;;;;;;;;;;;;;;;;;;;;AAqBtC,MAAa,MAAM;CAClB,MACC,KACA,QACA,WACI,UAAU,KAAK,QAAQ;EAAE,GAAG;EAAQ,QAAQ;EAAO,CAAC;CAEzD,OACC,KACA,QACA,MACA,WACI,UAAU,KAAK,QAAQ;EAAE,GAAG;EAAQ,QAAQ;EAAQ;EAAM,CAAC;CAEhE,MACC,KACA,QACA,MACA,WACI,UAAU,KAAK,QAAQ;EAAE,GAAG;EAAQ,QAAQ;EAAO;EAAM,CAAC;CAE/D,QACC,KACA,QACA,MACA,WACI,UAAU,KAAK,QAAQ;EAAE,GAAG;EAAQ,QAAQ;EAAS;EAAM,CAAC;CAEjE,SACC,KACA,QACA,WACI,UAAU,KAAK,QAAQ;EAAE,GAAG;EAAQ,QAAQ;EAAU,CAAC;CAC5D"}
@@ -1,2 +0,0 @@
1
- import { n as ResponseType, t as FetchConfig } from "../index-BkzLFXkF.js";
2
- export { FetchConfig, ResponseType };
File without changes