@cushin/api-runtime 4.0.3 → 4.1.5

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.
@@ -14,4 +14,4 @@ export {
14
14
  defineEndpoint,
15
15
  defineEndpoints
16
16
  };
17
- //# sourceMappingURL=chunk-GL2GG37G.js.map
17
+ //# sourceMappingURL=chunk-3FFXWCVP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts"],"sourcesContent":["import type { z } from \"zod\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport interface APIEndpoint {\n path: string;\n method: HTTPMethod;\n baseUrl?: string;\n params?: z.ZodType<any>;\n query?: z.ZodType<any>;\n body?: z.ZodType<any>;\n response: z.ZodType<any>;\n tags?: string[];\n description?: string;\n headers?: Record<string, string | undefined | null>;\n}\n\nexport interface APIConfig {\n baseUrl?: string;\n endpoints: Record<string, APIEndpoint>;\n}\n\nexport type EndpointConfig<\n TPath extends string = string,\n TMethod extends HTTPMethod = HTTPMethod,\n TParams = undefined,\n TQuery = undefined,\n TBody = undefined,\n TResponse = any,\n> = {\n path: TPath;\n method: TMethod;\n baseUrl?: string;\n params?: z.ZodType<TParams>;\n query?: z.ZodType<TQuery>;\n body?: z.ZodType<TBody>;\n response: z.ZodType<TResponse>;\n tags?: string[];\n description?: string;\n headers?: Record<string, string | undefined | null>;\n};\n\n/**\n * Helper function to define API configuration with type safety\n */\nexport function defineConfig<T extends APIConfig>(config: T): T {\n return config;\n}\n\n/**\n * Helper function to define a single endpoint with type inference\n */\nexport function defineEndpoint<\n TPath extends string,\n TMethod extends HTTPMethod,\n TParams = undefined,\n TQuery = undefined,\n TBody = undefined,\n TResponse = any,\n>(\n config: EndpointConfig<TPath, TMethod, TParams, TQuery, TBody, TResponse>,\n): EndpointConfig<TPath, TMethod, TParams, TQuery, TBody, TResponse> {\n return config;\n}\n\n/**\n * Helper to define multiple endpoints\n */\nexport function defineEndpoints<T extends Record<string, APIEndpoint>>(\n endpoints: T,\n): T {\n return endpoints;\n}\n"],"mappings":";AA6CO,SAAS,aAAkC,QAAc;AAC9D,SAAO;AACT;AAKO,SAAS,eAQd,QACmE;AACnE,SAAO;AACT;AAKO,SAAS,gBACd,WACG;AACH,SAAO;AACT;","names":[]}
@@ -148,6 +148,17 @@ var APIClient = class {
148
148
  const options = {
149
149
  method: endpoint.method
150
150
  };
151
+ if (endpoint.headers) {
152
+ options.headers = Object.entries(endpoint.headers).reduce(
153
+ (acc, [key, value]) => {
154
+ if (value !== void 0 && value !== null) {
155
+ acc[key] = value;
156
+ }
157
+ return acc;
158
+ },
159
+ {}
160
+ );
161
+ }
151
162
  if (query && Object.keys(query).length > 0) {
152
163
  const searchParams = new URLSearchParams();
153
164
  Object.entries(query).forEach(([key, value]) => {
@@ -160,7 +171,12 @@ var APIClient = class {
160
171
  }
161
172
  }
162
173
  if (body && endpoint.method !== "GET") {
163
- if (endpoint.body) {
174
+ if (body instanceof FormData) {
175
+ options.body = body;
176
+ if (options.headers && options.headers["Content-Type"]) {
177
+ delete options.headers["Content-Type"];
178
+ }
179
+ } else if (endpoint.body) {
164
180
  const validatedBody = endpoint.body.parse(body);
165
181
  options.json = validatedBody;
166
182
  } else {
@@ -260,4 +276,4 @@ export {
260
276
  APIClient,
261
277
  createAPIClient
262
278
  };
263
- //# sourceMappingURL=chunk-RJFROHWK.js.map
279
+ //# sourceMappingURL=chunk-MMXAPQKA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import ky, { HTTPError } from \"ky\";\nimport type { APIConfig, APIEndpoint } from \"./schema.js\";\n\nexport interface AuthTokens {\n accessToken: string;\n refreshToken?: string;\n}\n\nexport interface AuthCallbacks {\n getTokens: () => Promise<AuthTokens | null>;\n onAuthError?: () => void;\n onRefreshToken?: () => Promise<void>;\n}\n\nexport class APIError extends Error {\n constructor(\n message: string,\n public status: number,\n public response?: any,\n ) {\n super(message);\n this.name = \"APIError\";\n }\n}\n\nexport class AuthError extends APIError {\n constructor(message: string = \"Authentication failed\") {\n super(message, 401);\n this.name = \"AuthError\";\n }\n}\n\nexport class APIClient {\n private client: typeof ky;\n private isRefreshing = false;\n private refreshPromise: Promise<void> | null = null;\n private hooks: any;\n\n constructor(\n private config: APIConfig,\n private authCallbacks?: AuthCallbacks,\n ) {\n this.hooks = {\n beforeRequest: [\n async (request: Request) => {\n const tokens = await this.authCallbacks?.getTokens();\n if (tokens?.accessToken) {\n request.headers.set(\n \"Authorization\",\n `Bearer ${tokens.accessToken}`,\n );\n }\n },\n ],\n beforeRetry: [\n async ({ request, error, retryCount }: any) => {\n if (error instanceof HTTPError && error.response.status === 401) {\n if (retryCount === 1 && this.authCallbacks) {\n try {\n await this.refreshTokens();\n const tokens = await this.authCallbacks.getTokens();\n if (tokens?.accessToken) {\n request.headers.set(\n \"Authorization\",\n `Bearer ${tokens.accessToken}`,\n );\n }\n } catch (refreshError) {\n this.authCallbacks.onAuthError?.();\n throw new AuthError();\n }\n } else {\n this.authCallbacks?.onAuthError?.();\n throw new AuthError();\n }\n }\n },\n ],\n beforeError: [\n async (error: any) => {\n const { response } = error;\n if (response?.body) {\n try {\n const body = await response.json();\n error.message =\n (body as Error).message || `HTTP ${response.status}`;\n } catch {\n // Keep original message\n }\n }\n return error;\n },\n ],\n };\n\n this.client = ky.create({\n prefixUrl: this.config.baseUrl,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n retry: {\n limit: 2,\n methods: [\"get\", \"post\", \"put\", \"delete\", \"patch\"],\n statusCodes: [401],\n },\n hooks: this.hooks,\n });\n }\n\n private async refreshTokens(): Promise<void> {\n if (!this.authCallbacks) {\n throw new AuthError(\"No auth callbacks provided\");\n }\n\n if (this.isRefreshing && this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.isRefreshing = true;\n\n this.refreshPromise = (async () => {\n try {\n if (this.authCallbacks?.onRefreshToken) {\n await this.authCallbacks.onRefreshToken();\n } else {\n throw new AuthError(\"No refresh token handler provided\");\n }\n } catch (error) {\n throw error;\n } finally {\n this.isRefreshing = false;\n this.refreshPromise = null;\n }\n })();\n\n return this.refreshPromise;\n }\n\n private buildPath(path: string, params?: Record<string, any>): string {\n if (!params) return path;\n\n let finalPath = path;\n Object.entries(params).forEach(([key, value]) => {\n finalPath = finalPath.replace(\n `:${key}`,\n encodeURIComponent(String(value)),\n );\n });\n\n return finalPath;\n }\n\n private getEndpointBaseUrl(endpoint: APIEndpoint): string {\n return endpoint.baseUrl || this.config.baseUrl!;\n }\n\n private getClientForEndpoint(endpoint: APIEndpoint): typeof ky {\n const endpointBaseUrl = this.getEndpointBaseUrl(endpoint);\n\n if (endpointBaseUrl === this.config.baseUrl) {\n return this.client;\n }\n\n return ky.create({\n prefixUrl: endpointBaseUrl,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n retry: {\n limit: 2,\n methods: [\"get\", \"post\", \"put\", \"delete\", \"patch\"],\n statusCodes: [401],\n },\n hooks: this.hooks,\n });\n }\n\n async request<T>(\n endpoint: APIEndpoint,\n params?: Record<string, any>,\n query?: Record<string, any>,\n body?: any,\n ): Promise<T> {\n try {\n const path = this.buildPath(endpoint.path, params);\n const client = this.getClientForEndpoint(endpoint);\n\n const options: Record<string, any> = {\n method: endpoint.method,\n };\n\n // Apply custom headers if provided\n // Filter out undefined and null values to allow unsetting headers\n if (endpoint.headers) {\n options.headers = Object.entries(endpoint.headers).reduce(\n (acc, [key, value]) => {\n if (value !== undefined && value !== null) {\n acc[key] = value;\n }\n return acc;\n },\n {} as Record<string, string>,\n );\n }\n\n if (query && Object.keys(query).length > 0) {\n const searchParams = new URLSearchParams();\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n if (searchParams.toString()) {\n options.searchParams = searchParams;\n }\n }\n\n if (body && endpoint.method !== \"GET\") {\n // Check if body is FormData\n if (body instanceof FormData) {\n options.body = body;\n // Remove Content-Type header to let the browser set it with the correct boundary\n if (options.headers && options.headers[\"Content-Type\"]) {\n delete options.headers[\"Content-Type\"];\n }\n } else if (endpoint.body) {\n const validatedBody = endpoint.body.parse(body);\n options.json = validatedBody;\n } else {\n options.json = body;\n }\n }\n\n const response = await client(path, options);\n const data = await response.json();\n\n if (endpoint.response) {\n return endpoint.response.parse(data);\n }\n\n return data as T;\n } catch (error) {\n if (error instanceof HTTPError) {\n const errorData = await error.response.json().catch(() => ({}));\n throw new APIError(\n errorData.message || error.message,\n error.response.status,\n errorData,\n );\n }\n\n if (error instanceof AuthError) {\n throw error;\n }\n\n throw new APIError(\n error instanceof Error ? error.message : \"Network error\",\n 0,\n );\n }\n }\n\n updateAuthCallbacks(authCallbacks: AuthCallbacks) {\n this.authCallbacks = authCallbacks;\n }\n\n async refreshAuth(): Promise<void> {\n if (!this.authCallbacks) {\n throw new AuthError(\"No auth callbacks provided\");\n }\n await this.refreshTokens();\n }\n\n generateMethods() {\n const methods: any = {};\n\n Object.entries(this.config.endpoints).forEach(([name, endpoint]) => {\n if (endpoint.method === \"GET\") {\n if (endpoint.params && endpoint.query) {\n methods[name] = (params: any, query?: any): Promise<any> => {\n return this.request(endpoint, params, query);\n };\n } else if (endpoint.params) {\n methods[name] = (params: any): Promise<any> => {\n return this.request(endpoint, params);\n };\n } else if (endpoint.query) {\n methods[name] = (query?: any): Promise<any> => {\n return this.request(endpoint, undefined, query);\n };\n } else {\n methods[name] = (): Promise<any> => {\n return this.request(endpoint);\n };\n }\n } else {\n if (endpoint.params && endpoint.body) {\n methods[name] = (params: any, body: any): Promise<any> => {\n return this.request(endpoint, params, undefined, body);\n };\n } else if (endpoint.params) {\n methods[name] = (params: any): Promise<any> => {\n return this.request(endpoint, params);\n };\n } else if (endpoint.body) {\n methods[name] = (body: any): Promise<any> => {\n return this.request(endpoint, undefined, undefined, body);\n };\n } else {\n methods[name] = (): Promise<any> => {\n return this.request(endpoint);\n };\n }\n }\n });\n\n return methods;\n }\n}\n\nexport function createAPIClient(\n config: APIConfig,\n authCallbacks?: AuthCallbacks,\n) {\n const instance = new APIClient(config, authCallbacks);\n const methods = instance.generateMethods();\n\n return {\n ...methods,\n refreshAuth: () => instance.refreshAuth(),\n updateAuthCallbacks: (newCallbacks: AuthCallbacks) =>\n instance.updateAuthCallbacks(newCallbacks),\n };\n}\n"],"mappings":"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","names":[]}
package/dist/client.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  APIError,
4
4
  AuthError,
5
5
  createAPIClient
6
- } from "./chunk-RJFROHWK.js";
6
+ } from "./chunk-MMXAPQKA.js";
7
7
  export {
8
8
  APIClient,
9
9
  APIError,
package/dist/index.js CHANGED
@@ -3,12 +3,12 @@ import {
3
3
  APIError,
4
4
  AuthError,
5
5
  createAPIClient
6
- } from "./chunk-RJFROHWK.js";
6
+ } from "./chunk-MMXAPQKA.js";
7
7
  import {
8
8
  defineConfig,
9
9
  defineEndpoint,
10
10
  defineEndpoints
11
- } from "./chunk-GL2GG37G.js";
11
+ } from "./chunk-3FFXWCVP.js";
12
12
  export {
13
13
  APIClient,
14
14
  APIError,
package/dist/schema.d.ts CHANGED
@@ -11,6 +11,7 @@ interface APIEndpoint {
11
11
  response: z.ZodType<any>;
12
12
  tags?: string[];
13
13
  description?: string;
14
+ headers?: Record<string, string | undefined | null>;
14
15
  }
15
16
  interface APIConfig {
16
17
  baseUrl?: string;
@@ -26,6 +27,7 @@ type EndpointConfig<TPath extends string = string, TMethod extends HTTPMethod =
26
27
  response: z.ZodType<TResponse>;
27
28
  tags?: string[];
28
29
  description?: string;
30
+ headers?: Record<string, string | undefined | null>;
29
31
  };
30
32
  /**
31
33
  * Helper function to define API configuration with type safety
package/dist/schema.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  defineConfig,
3
3
  defineEndpoint,
4
4
  defineEndpoints
5
- } from "./chunk-GL2GG37G.js";
5
+ } from "./chunk-3FFXWCVP.js";
6
6
  export {
7
7
  defineConfig,
8
8
  defineEndpoint,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cushin/api-runtime",
3
- "version": "4.0.3",
3
+ "version": "4.1.5",
4
4
  "description": "Runtime utilities for Cushin API codegen - types, schemas, and HTTP client",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/schema.ts"],"sourcesContent":["import type { z } from \"zod\";\n\nexport type HTTPMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport interface APIEndpoint {\n path: string;\n method: HTTPMethod;\n baseUrl?: string;\n params?: z.ZodType<any>;\n query?: z.ZodType<any>;\n body?: z.ZodType<any>;\n response: z.ZodType<any>;\n tags?: string[];\n description?: string;\n}\n\nexport interface APIConfig {\n baseUrl?: string;\n endpoints: Record<string, APIEndpoint>;\n}\n\nexport type EndpointConfig<\n TPath extends string = string,\n TMethod extends HTTPMethod = HTTPMethod,\n TParams = undefined,\n TQuery = undefined,\n TBody = undefined,\n TResponse = any,\n> = {\n path: TPath;\n method: TMethod;\n baseUrl?: string;\n params?: z.ZodType<TParams>;\n query?: z.ZodType<TQuery>;\n body?: z.ZodType<TBody>;\n response: z.ZodType<TResponse>;\n tags?: string[];\n description?: string;\n};\n\n/**\n * Helper function to define API configuration with type safety\n */\nexport function defineConfig<T extends APIConfig>(config: T): T {\n return config;\n}\n\n/**\n * Helper function to define a single endpoint with type inference\n */\nexport function defineEndpoint<\n TPath extends string,\n TMethod extends HTTPMethod,\n TParams = undefined,\n TQuery = undefined,\n TBody = undefined,\n TResponse = any,\n>(\n config: EndpointConfig<TPath, TMethod, TParams, TQuery, TBody, TResponse>,\n): EndpointConfig<TPath, TMethod, TParams, TQuery, TBody, TResponse> {\n return config;\n}\n\n/**\n * Helper to define multiple endpoints\n */\nexport function defineEndpoints<T extends Record<string, APIEndpoint>>(\n endpoints: T,\n): T {\n return endpoints;\n}\n"],"mappings":";AA2CO,SAAS,aAAkC,QAAc;AAC9D,SAAO;AACT;AAKO,SAAS,eAQd,QACmE;AACnE,SAAO;AACT;AAKO,SAAS,gBACd,WACG;AACH,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import ky, { HTTPError } from \"ky\";\nimport type { APIConfig, APIEndpoint } from \"./schema.js\";\n\nexport interface AuthTokens {\n accessToken: string;\n refreshToken?: string;\n}\n\nexport interface AuthCallbacks {\n getTokens: () => Promise<AuthTokens | null>;\n onAuthError?: () => void;\n onRefreshToken?: () => Promise<void>;\n}\n\nexport class APIError extends Error {\n constructor(\n message: string,\n public status: number,\n public response?: any,\n ) {\n super(message);\n this.name = \"APIError\";\n }\n}\n\nexport class AuthError extends APIError {\n constructor(message: string = \"Authentication failed\") {\n super(message, 401);\n this.name = \"AuthError\";\n }\n}\n\nexport class APIClient {\n private client: typeof ky;\n private isRefreshing = false;\n private refreshPromise: Promise<void> | null = null;\n private hooks: any;\n\n constructor(\n private config: APIConfig,\n private authCallbacks?: AuthCallbacks,\n ) {\n this.hooks = {\n beforeRequest: [\n async (request: Request) => {\n const tokens = await this.authCallbacks?.getTokens();\n if (tokens?.accessToken) {\n request.headers.set(\n \"Authorization\",\n `Bearer ${tokens.accessToken}`,\n );\n }\n },\n ],\n beforeRetry: [\n async ({ request, error, retryCount }: any) => {\n if (error instanceof HTTPError && error.response.status === 401) {\n if (retryCount === 1 && this.authCallbacks) {\n try {\n await this.refreshTokens();\n const tokens = await this.authCallbacks.getTokens();\n if (tokens?.accessToken) {\n request.headers.set(\n \"Authorization\",\n `Bearer ${tokens.accessToken}`,\n );\n }\n } catch (refreshError) {\n this.authCallbacks.onAuthError?.();\n throw new AuthError();\n }\n } else {\n this.authCallbacks?.onAuthError?.();\n throw new AuthError();\n }\n }\n },\n ],\n beforeError: [\n async (error: any) => {\n const { response } = error;\n if (response?.body) {\n try {\n const body = await response.json();\n error.message =\n (body as Error).message || `HTTP ${response.status}`;\n } catch {\n // Keep original message\n }\n }\n return error;\n },\n ],\n };\n\n this.client = ky.create({\n prefixUrl: this.config.baseUrl,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n retry: {\n limit: 2,\n methods: [\"get\", \"post\", \"put\", \"delete\", \"patch\"],\n statusCodes: [401],\n },\n hooks: this.hooks,\n });\n }\n\n private async refreshTokens(): Promise<void> {\n if (!this.authCallbacks) {\n throw new AuthError(\"No auth callbacks provided\");\n }\n\n if (this.isRefreshing && this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.isRefreshing = true;\n\n this.refreshPromise = (async () => {\n try {\n if (this.authCallbacks?.onRefreshToken) {\n await this.authCallbacks.onRefreshToken();\n } else {\n throw new AuthError(\"No refresh token handler provided\");\n }\n } catch (error) {\n throw error;\n } finally {\n this.isRefreshing = false;\n this.refreshPromise = null;\n }\n })();\n\n return this.refreshPromise;\n }\n\n private buildPath(path: string, params?: Record<string, any>): string {\n if (!params) return path;\n\n let finalPath = path;\n Object.entries(params).forEach(([key, value]) => {\n finalPath = finalPath.replace(\n `:${key}`,\n encodeURIComponent(String(value)),\n );\n });\n\n return finalPath;\n }\n\n private getEndpointBaseUrl(endpoint: APIEndpoint): string {\n return endpoint.baseUrl || this.config.baseUrl!;\n }\n\n private getClientForEndpoint(endpoint: APIEndpoint): typeof ky {\n const endpointBaseUrl = this.getEndpointBaseUrl(endpoint);\n\n if (endpointBaseUrl === this.config.baseUrl) {\n return this.client;\n }\n\n return ky.create({\n prefixUrl: endpointBaseUrl,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n retry: {\n limit: 2,\n methods: [\"get\", \"post\", \"put\", \"delete\", \"patch\"],\n statusCodes: [401],\n },\n hooks: this.hooks,\n });\n }\n\n async request<T>(\n endpoint: APIEndpoint,\n params?: Record<string, any>,\n query?: Record<string, any>,\n body?: any,\n ): Promise<T> {\n try {\n const path = this.buildPath(endpoint.path, params);\n const client = this.getClientForEndpoint(endpoint);\n\n const options: Record<string, any> = {\n method: endpoint.method,\n };\n\n if (query && Object.keys(query).length > 0) {\n const searchParams = new URLSearchParams();\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n if (searchParams.toString()) {\n options.searchParams = searchParams;\n }\n }\n\n if (body && endpoint.method !== \"GET\") {\n if (endpoint.body) {\n const validatedBody = endpoint.body.parse(body);\n options.json = validatedBody;\n } else {\n options.json = body;\n }\n }\n\n const response = await client(path, options);\n const data = await response.json();\n\n if (endpoint.response) {\n return endpoint.response.parse(data);\n }\n\n return data as T;\n } catch (error) {\n if (error instanceof HTTPError) {\n const errorData = await error.response.json().catch(() => ({}));\n throw new APIError(\n errorData.message || error.message,\n error.response.status,\n errorData,\n );\n }\n\n if (error instanceof AuthError) {\n throw error;\n }\n\n throw new APIError(\n error instanceof Error ? error.message : \"Network error\",\n 0,\n );\n }\n }\n\n updateAuthCallbacks(authCallbacks: AuthCallbacks) {\n this.authCallbacks = authCallbacks;\n }\n\n async refreshAuth(): Promise<void> {\n if (!this.authCallbacks) {\n throw new AuthError(\"No auth callbacks provided\");\n }\n await this.refreshTokens();\n }\n\n generateMethods() {\n const methods: any = {};\n\n Object.entries(this.config.endpoints).forEach(([name, endpoint]) => {\n if (endpoint.method === \"GET\") {\n if (endpoint.params && endpoint.query) {\n methods[name] = (params: any, query?: any): Promise<any> => {\n return this.request(endpoint, params, query);\n };\n } else if (endpoint.params) {\n methods[name] = (params: any): Promise<any> => {\n return this.request(endpoint, params);\n };\n } else if (endpoint.query) {\n methods[name] = (query?: any): Promise<any> => {\n return this.request(endpoint, undefined, query);\n };\n } else {\n methods[name] = (): Promise<any> => {\n return this.request(endpoint);\n };\n }\n } else {\n if (endpoint.params && endpoint.body) {\n methods[name] = (params: any, body: any): Promise<any> => {\n return this.request(endpoint, params, undefined, body);\n };\n } else if (endpoint.params) {\n methods[name] = (params: any): Promise<any> => {\n return this.request(endpoint, params);\n };\n } else if (endpoint.body) {\n methods[name] = (body: any): Promise<any> => {\n return this.request(endpoint, undefined, undefined, body);\n };\n } else {\n methods[name] = (): Promise<any> => {\n return this.request(endpoint);\n };\n }\n }\n });\n\n return methods;\n }\n}\n\nexport function createAPIClient(\n config: APIConfig,\n authCallbacks?: AuthCallbacks,\n) {\n const instance = new APIClient(config, authCallbacks);\n const methods = instance.generateMethods();\n\n return {\n ...methods,\n refreshAuth: () => instance.refreshAuth(),\n updateAuthCallbacks: (newCallbacks: AuthCallbacks) =>\n instance.updateAuthCallbacks(newCallbacks),\n };\n}\n"],"mappings":"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","names":[]}