@spfn/core 0.1.0-alpha.88 → 0.2.0-beta.1

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.
Files changed (71) hide show
  1. package/README.md +1046 -384
  2. package/dist/boss-D-fGtVgM.d.ts +187 -0
  3. package/dist/cache/index.d.ts +13 -33
  4. package/dist/cache/index.js +14 -703
  5. package/dist/cache/index.js.map +1 -1
  6. package/dist/codegen/index.d.ts +167 -17
  7. package/dist/codegen/index.js +76 -1419
  8. package/dist/codegen/index.js.map +1 -1
  9. package/dist/config/index.d.ts +1191 -0
  10. package/dist/config/index.js +264 -0
  11. package/dist/config/index.js.map +1 -0
  12. package/dist/db/index.d.ts +728 -59
  13. package/dist/db/index.js +1028 -1225
  14. package/dist/db/index.js.map +1 -1
  15. package/dist/env/index.d.ts +579 -308
  16. package/dist/env/index.js +438 -930
  17. package/dist/env/index.js.map +1 -1
  18. package/dist/errors/index.d.ts +417 -29
  19. package/dist/errors/index.js +359 -98
  20. package/dist/errors/index.js.map +1 -1
  21. package/dist/event/index.d.ts +108 -0
  22. package/dist/event/index.js +122 -0
  23. package/dist/event/index.js.map +1 -0
  24. package/dist/job/index.d.ts +172 -0
  25. package/dist/job/index.js +361 -0
  26. package/dist/job/index.js.map +1 -0
  27. package/dist/logger/index.d.ts +20 -79
  28. package/dist/logger/index.js +82 -387
  29. package/dist/logger/index.js.map +1 -1
  30. package/dist/middleware/index.d.ts +2 -11
  31. package/dist/middleware/index.js +49 -703
  32. package/dist/middleware/index.js.map +1 -1
  33. package/dist/nextjs/index.d.ts +120 -0
  34. package/dist/nextjs/index.js +416 -0
  35. package/dist/nextjs/index.js.map +1 -0
  36. package/dist/{client/nextjs/index.d.ts → nextjs/server.d.ts} +288 -262
  37. package/dist/nextjs/server.js +568 -0
  38. package/dist/nextjs/server.js.map +1 -0
  39. package/dist/route/index.d.ts +667 -25
  40. package/dist/route/index.js +437 -1287
  41. package/dist/route/index.js.map +1 -1
  42. package/dist/route/types.d.ts +38 -0
  43. package/dist/route/types.js +3 -0
  44. package/dist/route/types.js.map +1 -0
  45. package/dist/server/index.d.ts +201 -67
  46. package/dist/server/index.js +921 -3182
  47. package/dist/server/index.js.map +1 -1
  48. package/dist/types-BGl4QL1w.d.ts +77 -0
  49. package/dist/types-DRG2XMTR.d.ts +157 -0
  50. package/package.json +52 -47
  51. package/dist/auto-loader-JFaZ9gON.d.ts +0 -80
  52. package/dist/client/index.d.ts +0 -358
  53. package/dist/client/index.js +0 -357
  54. package/dist/client/index.js.map +0 -1
  55. package/dist/client/nextjs/index.js +0 -371
  56. package/dist/client/nextjs/index.js.map +0 -1
  57. package/dist/codegen/generators/index.d.ts +0 -19
  58. package/dist/codegen/generators/index.js +0 -1404
  59. package/dist/codegen/generators/index.js.map +0 -1
  60. package/dist/database-errors-BNNmLTJE.d.ts +0 -86
  61. package/dist/events/index.d.ts +0 -183
  62. package/dist/events/index.js +0 -77
  63. package/dist/events/index.js.map +0 -1
  64. package/dist/index-DHiAqhKv.d.ts +0 -101
  65. package/dist/index.d.ts +0 -8
  66. package/dist/index.js +0 -3674
  67. package/dist/index.js.map +0 -1
  68. package/dist/types/index.d.ts +0 -121
  69. package/dist/types/index.js +0 -38
  70. package/dist/types/index.js.map +0 -1
  71. package/dist/types-BXibIEyj.d.ts +0 -60
@@ -1,358 +0,0 @@
1
- import '../auto-loader-JFaZ9gON.js';
2
- import { a as RouteContract, I as InferContract } from '../types-BXibIEyj.js';
3
- import 'hono';
4
- import 'hono/utils/http-status';
5
- import '@sinclair/typebox';
6
- import '../types/index.js';
7
-
8
- /**
9
- * Contract-Based API Client
10
- *
11
- * Type-safe HTTP client that works with RouteContract for full end-to-end type safety
12
- */
13
-
14
- type RequestInterceptor = (url: string, init: RequestInit) => Promise<RequestInit> | RequestInit;
15
- interface ClientConfig {
16
- /**
17
- * API base URL (e.g., http://localhost:4000)
18
- */
19
- baseUrl?: string;
20
- /**
21
- * Default headers to include in all requests
22
- */
23
- headers?: Record<string, string>;
24
- /**
25
- * Request timeout in milliseconds
26
- */
27
- timeout?: number;
28
- /**
29
- * Custom fetch implementation
30
- */
31
- fetch?: typeof fetch;
32
- }
33
- interface CallOptions<TContract extends RouteContract> {
34
- params?: InferContract<TContract>['params'];
35
- query?: InferContract<TContract>['query'];
36
- body?: InferContract<TContract>['body'];
37
- headers?: Record<string, string>;
38
- baseUrl?: string;
39
- /**
40
- * Additional fetch options (extends RequestInit)
41
- *
42
- * Can be used for environment-specific options like Next.js cache/next
43
- *
44
- * @example
45
- * ```ts
46
- * // Next.js time-based revalidation
47
- * { fetchOptions: { next: { revalidate: 60 } } }
48
- *
49
- * // Next.js disable cache
50
- * { fetchOptions: { cache: 'no-store' } }
51
- *
52
- * // Next.js on-demand revalidation
53
- * { fetchOptions: { next: { tags: ['products'] } } }
54
- * ```
55
- */
56
- fetchOptions?: Record<string, any>;
57
- }
58
- /**
59
- * API Client Error
60
- */
61
- declare class ApiClientError extends Error {
62
- readonly status: number;
63
- readonly url: string;
64
- readonly response?: unknown | undefined;
65
- readonly errorType?: "timeout" | "network" | "http" | undefined;
66
- constructor(message: string, status: number, url: string, response?: unknown | undefined, errorType?: "timeout" | "network" | "http" | undefined);
67
- }
68
- /**
69
- * Contract-based API Client
70
- */
71
- declare class ContractClient {
72
- private readonly config;
73
- private readonly interceptors;
74
- constructor(config?: ClientConfig);
75
- /**
76
- * Add request interceptor
77
- */
78
- use(interceptor: RequestInterceptor): void;
79
- /**
80
- * Make a type-safe API call using a contract
81
- *
82
- * @param contract - Route contract with absolute path
83
- * @param options - Call options (params, query, body, headers)
84
- */
85
- call<TContract extends RouteContract>(contract: TContract, options?: CallOptions<TContract>): Promise<InferContract<TContract>['response']>;
86
- /**
87
- * Create a new client with merged configuration
88
- */
89
- withConfig(config: Partial<ClientConfig>): ContractClient;
90
- private static buildUrl;
91
- private static buildQuery;
92
- private static getHttpMethod;
93
- private static isFormData;
94
- }
95
- /**
96
- * Type guard for timeout errors
97
- *
98
- * @example
99
- * ```ts
100
- * try {
101
- * await api.users.getById({ params: { id: '123' } });
102
- * } catch (error) {
103
- * if (isTimeoutError(error)) {
104
- * console.error('Request timed out, retrying...');
105
- * // Implement retry logic
106
- * }
107
- * }
108
- * ```
109
- */
110
- declare function isTimeoutError(error: unknown): error is ApiClientError;
111
- /**
112
- * Type guard for network errors
113
- *
114
- * @example
115
- * ```ts
116
- * try {
117
- * await api.users.list();
118
- * } catch (error) {
119
- * if (isNetworkError(error)) {
120
- * showOfflineMessage();
121
- * }
122
- * }
123
- * ```
124
- */
125
- declare function isNetworkError(error: unknown): error is ApiClientError;
126
- /**
127
- * Type guard for HTTP errors (4xx, 5xx)
128
- *
129
- * @example
130
- * ```ts
131
- * try {
132
- * await api.users.create({ body: userData });
133
- * } catch (error) {
134
- * if (isHttpError(error)) {
135
- * if (error.status === 401) {
136
- * redirectToLogin();
137
- * } else if (error.status === 404) {
138
- * showNotFoundMessage();
139
- * }
140
- * }
141
- * }
142
- * ```
143
- */
144
- declare function isHttpError(error: unknown): error is ApiClientError;
145
- /**
146
- * Check if error is a specific server error type
147
- *
148
- * @example
149
- * ```ts
150
- * try {
151
- * await api.workflows.getById({ params: { uuid: 'xxx' } });
152
- * } catch (error) {
153
- * if (isServerError(error, 'NotFoundError')) {
154
- * showNotFoundMessage();
155
- * } else if (isServerError(error, 'ValidationError')) {
156
- * showValidationErrors(getServerErrorDetails(error));
157
- * }
158
- * }
159
- * ```
160
- */
161
- declare function isServerError(error: unknown, errorType: string): error is ApiClientError;
162
- /**
163
- * Get server error type from ApiClientError
164
- *
165
- * @example
166
- * ```ts
167
- * const errorType = getServerErrorType(error);
168
- * // 'NotFoundError', 'ValidationError', 'PaymentFailedError', etc.
169
- * ```
170
- */
171
- declare function getServerErrorType(error: ApiClientError): string | undefined;
172
- /**
173
- * Get server error details from ApiClientError
174
- *
175
- * @example
176
- * ```ts
177
- * if (isServerError(error, 'PaymentFailedError')) {
178
- * const details = getServerErrorDetails(error);
179
- * console.log('Payment ID:', details.paymentId);
180
- * }
181
- * ```
182
- */
183
- declare function getServerErrorDetails<T = any>(error: ApiClientError): T | undefined;
184
-
185
- /**
186
- * Universal API Client
187
- *
188
- * Automatically routes requests based on execution environment:
189
- * - Server Environment: Direct call to SPFN API (internal network)
190
- * - Browser Environment: Proxies through Next.js API Route (cookie forwarding)
191
- */
192
-
193
- /**
194
- * Universal Client Configuration
195
- */
196
- interface UniversalClientConfig {
197
- /**
198
- * SPFN API server URL (for server-side direct calls)
199
- *
200
- * @default process.env.SERVER_API_URL || process.env.SPFN_API_URL || 'http://localhost:8790'
201
- */
202
- apiUrl?: string;
203
- /**
204
- * Next.js API route base path (for client-side proxy calls)
205
- *
206
- * @default '/api/actions'
207
- * @example '/api/proxy'
208
- */
209
- proxyBasePath?: string;
210
- /**
211
- * Additional headers to include in all requests
212
- */
213
- headers?: Record<string, string>;
214
- /**
215
- * Request timeout in milliseconds
216
- *
217
- * @default 30000
218
- */
219
- timeout?: number;
220
- /**
221
- * Custom fetch implementation
222
- */
223
- fetch?: typeof fetch;
224
- }
225
- /**
226
- * Universal API Client
227
- *
228
- * Automatically detects execution environment and routes requests accordingly:
229
- *
230
- * **Server Environment** (Next.js Server Components, API Routes):
231
- * - Direct HTTP call to SPFN API server
232
- * - Uses internal network (e.g., http://localhost:8790)
233
- * - No proxy overhead
234
- *
235
- * **Browser Environment** (Next.js Client Components):
236
- * - Routes through Next.js API Route proxy (e.g., /api/proxy/*)
237
- * - Enables HttpOnly cookie forwarding
238
- * - Maintains CORS security
239
- *
240
- * @example
241
- * ```typescript
242
- * // Server Component - direct call
243
- * import { createUniversalClient } from '@spfn/core/client';
244
- * const client = createUniversalClient();
245
- * const result = await client.call(loginContract, { body: {...} });
246
- *
247
- * // Client Component - proxied call (automatic)
248
- * 'use client';
249
- * const client = createUniversalClient();
250
- * const result = await client.call(loginContract, { body: {...} }); // Goes through /api/proxy
251
- * ```
252
- */
253
- declare class UniversalClient {
254
- private readonly directClient;
255
- private readonly proxyBasePath;
256
- private readonly isServer;
257
- private readonly fetchImpl;
258
- constructor(config?: UniversalClientConfig);
259
- /**
260
- * Make a type-safe API call using a contract
261
- *
262
- * Automatically routes based on environment:
263
- * - Server: Direct SPFN API call
264
- * - Browser: Next.js API Route proxy
265
- *
266
- * @param contract - Route contract with absolute path
267
- * @param options - Call options (params, query, body, headers)
268
- */
269
- call<TContract extends RouteContract>(contract: TContract, options?: CallOptions<TContract>): Promise<InferContract<TContract>['response']>;
270
- /**
271
- * Call via Next.js API Route proxy (client-side)
272
- *
273
- * Routes request through /api/proxy/[...path] to enable:
274
- * - HttpOnly cookie forwarding
275
- * - CORS security
276
- * - Server-side session management
277
- *
278
- * @private
279
- */
280
- private callViaProxy;
281
- /**
282
- * Build URL path with parameter substitution
283
- */
284
- private buildUrlPath;
285
- /**
286
- * Build query string from query parameters
287
- */
288
- private buildQueryString;
289
- /**
290
- * Get HTTP method from contract or infer from options
291
- */
292
- private getHttpMethod;
293
- /**
294
- * Check if body is FormData
295
- */
296
- private isFormData;
297
- /**
298
- * Check if currently running in server environment
299
- */
300
- isServerEnv(): boolean;
301
- /**
302
- * Create a new client with merged configuration
303
- */
304
- withConfig(config: Partial<UniversalClientConfig>): UniversalClient;
305
- }
306
- /**
307
- * Create a new universal API client
308
- *
309
- * @example
310
- * ```typescript
311
- * // Default configuration
312
- * const client = createUniversalClient();
313
- *
314
- * // Custom configuration
315
- * const client = createUniversalClient({
316
- * apiUrl: 'http://localhost:4000',
317
- * proxyBasePath: '/api/spfn',
318
- * headers: { 'X-App-Version': '1.0.0' },
319
- * });
320
- * ```
321
- */
322
- declare function createUniversalClient(config?: UniversalClientConfig): UniversalClient;
323
- /**
324
- * Configure the global universal client instance
325
- *
326
- * Call this in your app initialization to set default configuration
327
- * for all auto-generated API calls.
328
- *
329
- * @example
330
- * ```typescript
331
- * // In app initialization (layout.tsx, _app.tsx, etc)
332
- * import { configureUniversalClient } from '@spfn/core/client';
333
- *
334
- * configureUniversalClient({
335
- * apiUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8790',
336
- * proxyBasePath: '/api/proxy',
337
- * headers: {
338
- * 'X-App-Version': '1.0.0'
339
- * }
340
- * });
341
- * ```
342
- */
343
- declare function configureUniversalClient(config: UniversalClientConfig): void;
344
- /**
345
- * Get the global universal client instance
346
- *
347
- * Creates a default instance if not configured
348
- */
349
- declare function getUniversalClient(): UniversalClient;
350
- /**
351
- * Global universal client singleton with Proxy
352
- *
353
- * This client can be configured using configureUniversalClient() before use.
354
- * Used by auto-generated API client code.
355
- */
356
- declare const universalClient: UniversalClient;
357
-
358
- export { ApiClientError, type CallOptions, type UniversalClientConfig as ClientConfig, ContractClient, type RequestInterceptor, UniversalClient, type UniversalClientConfig, universalClient as client, configureUniversalClient as configureClient, configureUniversalClient, createUniversalClient as createClient, createUniversalClient, getServerErrorDetails, getServerErrorType, getUniversalClient, isHttpError, isNetworkError, isServerError, isTimeoutError, universalClient };
@@ -1,357 +0,0 @@
1
- // src/client/contract-client.ts
2
- var ApiClientError = class extends Error {
3
- constructor(message, status, url, response, errorType) {
4
- super(message);
5
- this.status = status;
6
- this.url = url;
7
- this.response = response;
8
- this.errorType = errorType;
9
- this.name = "ApiClientError";
10
- }
11
- };
12
- var ContractClient = class _ContractClient {
13
- config;
14
- interceptors = [];
15
- constructor(config = {}) {
16
- this.config = {
17
- baseUrl: config.baseUrl || process.env.SERVER_API_URL || process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000",
18
- headers: config.headers || {},
19
- timeout: config.timeout || 3e4,
20
- fetch: config.fetch || globalThis.fetch.bind(globalThis)
21
- };
22
- }
23
- /**
24
- * Add request interceptor
25
- */
26
- use(interceptor) {
27
- this.interceptors.push(interceptor);
28
- }
29
- /**
30
- * Make a type-safe API call using a contract
31
- *
32
- * @param contract - Route contract with absolute path
33
- * @param options - Call options (params, query, body, headers)
34
- */
35
- async call(contract, options) {
36
- const baseUrl = options?.baseUrl || this.config.baseUrl;
37
- const urlPath = _ContractClient.buildUrl(
38
- contract.path,
39
- options?.params
40
- );
41
- const queryString = _ContractClient.buildQuery(
42
- options?.query
43
- );
44
- const url = `${baseUrl}${urlPath}${queryString}`;
45
- const method = _ContractClient.getHttpMethod(contract, options);
46
- const headers = {
47
- ...this.config.headers,
48
- ...options?.headers
49
- };
50
- const isFormData = _ContractClient.isFormData(options?.body);
51
- if (options?.body !== void 0 && !isFormData && !headers["Content-Type"]) {
52
- headers["Content-Type"] = "application/json";
53
- }
54
- let init = {
55
- method,
56
- headers,
57
- ...options?.fetchOptions
58
- // Spread environment-specific options (e.g., Next.js cache/next)
59
- };
60
- if (options?.body !== void 0) {
61
- init.body = isFormData ? options.body : JSON.stringify(options.body);
62
- }
63
- const controller = new AbortController();
64
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
65
- init.signal = controller.signal;
66
- for (const interceptor of this.interceptors) {
67
- init = await interceptor(url, init);
68
- }
69
- const response = await this.config.fetch(url, init).catch((error) => {
70
- clearTimeout(timeoutId);
71
- if (error instanceof Error && error.name === "AbortError") {
72
- throw new ApiClientError(
73
- `Request timed out after ${this.config.timeout}ms`,
74
- 0,
75
- url,
76
- void 0,
77
- "timeout"
78
- );
79
- }
80
- if (error instanceof Error) {
81
- throw new ApiClientError(
82
- `Network error: ${error.message}`,
83
- 0,
84
- url,
85
- void 0,
86
- "network"
87
- );
88
- }
89
- throw error;
90
- });
91
- clearTimeout(timeoutId);
92
- if (!response.ok) {
93
- const errorBody = await response.json().catch(() => null);
94
- throw new ApiClientError(
95
- `${method} ${urlPath} failed: ${response.status} ${response.statusText}`,
96
- response.status,
97
- url,
98
- errorBody,
99
- "http"
100
- );
101
- }
102
- const data = await response.json();
103
- return data;
104
- }
105
- /**
106
- * Create a new client with merged configuration
107
- */
108
- withConfig(config) {
109
- return new _ContractClient({
110
- baseUrl: config.baseUrl || this.config.baseUrl,
111
- headers: { ...this.config.headers, ...config.headers },
112
- timeout: config.timeout || this.config.timeout,
113
- fetch: config.fetch || this.config.fetch
114
- });
115
- }
116
- static buildUrl(path, params) {
117
- if (!params) return path;
118
- let url = path;
119
- for (const [key, value] of Object.entries(params)) {
120
- url = url.replace(`:${key}`, String(value));
121
- }
122
- return url;
123
- }
124
- static buildQuery(query) {
125
- if (!query || Object.keys(query).length === 0) return "";
126
- const params = new URLSearchParams();
127
- for (const [key, value] of Object.entries(query)) {
128
- if (Array.isArray(value)) {
129
- value.forEach((v) => params.append(key, String(v)));
130
- } else if (value !== void 0 && value !== null) {
131
- params.append(key, String(value));
132
- }
133
- }
134
- const queryString = params.toString();
135
- return queryString ? `?${queryString}` : "";
136
- }
137
- static getHttpMethod(contract, options) {
138
- if ("method" in contract && typeof contract.method === "string") {
139
- return contract.method.toUpperCase();
140
- }
141
- if (options?.body !== void 0) {
142
- return "POST";
143
- }
144
- return "GET";
145
- }
146
- static isFormData(body) {
147
- return body instanceof FormData;
148
- }
149
- };
150
- var _clientInstance = new ContractClient();
151
- new Proxy({}, {
152
- get(_target, prop) {
153
- return _clientInstance[prop];
154
- }
155
- });
156
- function isTimeoutError(error) {
157
- return error instanceof ApiClientError && error.errorType === "timeout";
158
- }
159
- function isNetworkError(error) {
160
- return error instanceof ApiClientError && error.errorType === "network";
161
- }
162
- function isHttpError(error) {
163
- return error instanceof ApiClientError && error.errorType === "http";
164
- }
165
- function isServerError(error, errorType) {
166
- if (!isHttpError(error)) return false;
167
- const response = error.response;
168
- return response?.error?.type === errorType;
169
- }
170
- function getServerErrorType(error) {
171
- const response = error.response;
172
- return response?.error?.type;
173
- }
174
- function getServerErrorDetails(error) {
175
- const response = error.response;
176
- return response?.error?.details;
177
- }
178
-
179
- // src/client/universal-client.ts
180
- function isServerEnvironment() {
181
- return typeof window === "undefined";
182
- }
183
- var UniversalClient = class _UniversalClient {
184
- directClient;
185
- proxyBasePath;
186
- isServer;
187
- fetchImpl;
188
- constructor(config = {}) {
189
- this.isServer = isServerEnvironment();
190
- this.directClient = new ContractClient({
191
- baseUrl: config.apiUrl,
192
- headers: config.headers,
193
- timeout: config.timeout,
194
- fetch: config.fetch
195
- });
196
- this.proxyBasePath = config.proxyBasePath || "/api/actions";
197
- this.fetchImpl = config.fetch || globalThis.fetch.bind(globalThis);
198
- }
199
- /**
200
- * Make a type-safe API call using a contract
201
- *
202
- * Automatically routes based on environment:
203
- * - Server: Direct SPFN API call
204
- * - Browser: Next.js API Route proxy
205
- *
206
- * @param contract - Route contract with absolute path
207
- * @param options - Call options (params, query, body, headers)
208
- */
209
- async call(contract, options) {
210
- if (this.isServer) {
211
- return this.directClient.call(contract, options);
212
- } else {
213
- return this.callViaProxy(contract, options);
214
- }
215
- }
216
- /**
217
- * Call via Next.js API Route proxy (client-side)
218
- *
219
- * Routes request through /api/proxy/[...path] to enable:
220
- * - HttpOnly cookie forwarding
221
- * - CORS security
222
- * - Server-side session management
223
- *
224
- * @private
225
- */
226
- async callViaProxy(contract, options) {
227
- const path = this.buildUrlPath(
228
- contract.path,
229
- options?.params
230
- );
231
- const queryString = this.buildQueryString(
232
- options?.query
233
- );
234
- const proxyUrl = `${this.proxyBasePath}${path}${queryString}`;
235
- const method = this.getHttpMethod(contract, options);
236
- const headers = {
237
- ...options?.headers
238
- };
239
- const isFormData = this.isFormData(options?.body);
240
- if (options?.body !== void 0 && !isFormData && !headers["Content-Type"]) {
241
- headers["Content-Type"] = "application/json";
242
- }
243
- const init = {
244
- method,
245
- headers,
246
- credentials: "include",
247
- // Important: Include cookies for session
248
- ...options?.fetchOptions
249
- // Spread environment-specific options (e.g., Next.js cache/next)
250
- };
251
- if (options?.body !== void 0) {
252
- init.body = isFormData ? options.body : JSON.stringify(options.body);
253
- }
254
- const response = await this.fetchImpl(proxyUrl, init);
255
- if (!response.ok) {
256
- const errorBody = await response.json().catch(() => null);
257
- throw new ApiClientError(
258
- `${method} ${path} failed: ${response.status} ${response.statusText}`,
259
- response.status,
260
- proxyUrl,
261
- errorBody,
262
- "http"
263
- );
264
- }
265
- const data = await response.json();
266
- return data;
267
- }
268
- /**
269
- * Build URL path with parameter substitution
270
- */
271
- buildUrlPath(path, params) {
272
- if (!params) return path;
273
- let url = path;
274
- for (const [key, value] of Object.entries(params)) {
275
- url = url.replace(`:${key}`, String(value));
276
- }
277
- return url;
278
- }
279
- /**
280
- * Build query string from query parameters
281
- */
282
- buildQueryString(query) {
283
- if (!query || Object.keys(query).length === 0) return "";
284
- const params = new URLSearchParams();
285
- for (const [key, value] of Object.entries(query)) {
286
- if (Array.isArray(value)) {
287
- value.forEach((v) => params.append(key, String(v)));
288
- } else if (value !== void 0 && value !== null) {
289
- params.append(key, String(value));
290
- }
291
- }
292
- const queryString = params.toString();
293
- return queryString ? `?${queryString}` : "";
294
- }
295
- /**
296
- * Get HTTP method from contract or infer from options
297
- */
298
- getHttpMethod(contract, options) {
299
- if ("method" in contract && typeof contract.method === "string") {
300
- return contract.method.toUpperCase();
301
- }
302
- if (options?.body !== void 0) {
303
- return "POST";
304
- }
305
- return "GET";
306
- }
307
- /**
308
- * Check if body is FormData
309
- */
310
- isFormData(body) {
311
- return typeof FormData !== "undefined" && body instanceof FormData;
312
- }
313
- /**
314
- * Check if currently running in server environment
315
- */
316
- isServerEnv() {
317
- return this.isServer;
318
- }
319
- /**
320
- * Create a new client with merged configuration
321
- */
322
- withConfig(config) {
323
- return new _UniversalClient({
324
- apiUrl: config.apiUrl || this.directClient["config"].baseUrl,
325
- proxyBasePath: config.proxyBasePath || this.proxyBasePath,
326
- headers: {
327
- ...this.directClient["config"].headers,
328
- ...config.headers
329
- },
330
- timeout: config.timeout || this.directClient["config"].timeout,
331
- fetch: config.fetch || this.fetchImpl
332
- });
333
- }
334
- };
335
- function createUniversalClient(config) {
336
- return new UniversalClient(config);
337
- }
338
- var _universalClientInstance = null;
339
- function configureUniversalClient(config) {
340
- _universalClientInstance = new UniversalClient(config);
341
- }
342
- function getUniversalClient() {
343
- if (!_universalClientInstance) {
344
- _universalClientInstance = new UniversalClient();
345
- }
346
- return _universalClientInstance;
347
- }
348
- var universalClient = new Proxy({}, {
349
- get(_target, prop) {
350
- const instance = getUniversalClient();
351
- return instance[prop];
352
- }
353
- });
354
-
355
- export { ApiClientError, ContractClient, UniversalClient, universalClient as client, configureUniversalClient as configureClient, configureUniversalClient, createUniversalClient as createClient, createUniversalClient, getServerErrorDetails, getServerErrorType, getUniversalClient, isHttpError, isNetworkError, isServerError, isTimeoutError, universalClient };
356
- //# sourceMappingURL=index.js.map
357
- //# sourceMappingURL=index.js.map