@djangocfg/monitor 2.1.322 → 2.1.327

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 (74) hide show
  1. package/dist/client.cjs +956 -1126
  2. package/dist/client.cjs.map +1 -1
  3. package/dist/client.d.cts +25 -39
  4. package/dist/client.d.ts +25 -39
  5. package/dist/client.mjs +956 -1137
  6. package/dist/client.mjs.map +1 -1
  7. package/dist/index.cjs +934 -1092
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +25 -39
  10. package/dist/index.d.ts +25 -39
  11. package/dist/index.mjs +927 -1096
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/server.cjs +915 -1092
  14. package/dist/server.cjs.map +1 -1
  15. package/dist/server.d.cts +25 -39
  16. package/dist/server.d.ts +25 -39
  17. package/dist/server.mjs +907 -1095
  18. package/dist/server.mjs.map +1 -1
  19. package/package.json +7 -2
  20. package/src/_api/generated/_shared/errors.ts +70 -0
  21. package/src/_api/generated/_shared/index.ts +25 -0
  22. package/src/_api/generated/_shared/logger.ts +123 -0
  23. package/src/_api/generated/_shared/storage.ts +83 -0
  24. package/src/_api/generated/_shared/validation-events.ts +52 -0
  25. package/src/_api/generated/cfg_monitor/api.ts +122 -0
  26. package/src/_api/generated/cfg_monitor/client/client.gen.ts +280 -0
  27. package/src/_api/generated/cfg_monitor/client/index.ts +25 -0
  28. package/src/_api/generated/cfg_monitor/client/types.gen.ts +217 -0
  29. package/src/_api/generated/cfg_monitor/client/utils.gen.ts +318 -0
  30. package/src/_api/generated/cfg_monitor/client.gen.ts +16 -0
  31. package/src/_api/generated/cfg_monitor/core/auth.gen.ts +41 -0
  32. package/src/_api/generated/cfg_monitor/core/bodySerializer.gen.ts +82 -0
  33. package/src/_api/generated/cfg_monitor/core/params.gen.ts +169 -0
  34. package/src/_api/generated/cfg_monitor/core/pathSerializer.gen.ts +171 -0
  35. package/src/_api/generated/cfg_monitor/core/queryKeySerializer.gen.ts +117 -0
  36. package/src/_api/generated/cfg_monitor/core/serverSentEvents.gen.ts +242 -0
  37. package/src/_api/generated/cfg_monitor/core/types.gen.ts +104 -0
  38. package/src/_api/generated/cfg_monitor/core/utils.gen.ts +140 -0
  39. package/src/_api/generated/cfg_monitor/events.ts +198 -0
  40. package/src/_api/generated/cfg_monitor/hooks/index.ts +4 -0
  41. package/src/_api/generated/cfg_monitor/hooks/useCfgMonitorIngestCreate.ts +24 -0
  42. package/src/_api/generated/cfg_monitor/index.ts +26 -314
  43. package/src/_api/generated/cfg_monitor/schemas/EventTypeEnum.ts +9 -0
  44. package/src/_api/generated/cfg_monitor/{_utils/schemas/FrontendEventIngestRequest.schema.ts → schemas/FrontendEventIngestRequest.ts} +12 -19
  45. package/src/_api/generated/cfg_monitor/schemas/IngestBatchRequest.ts +12 -0
  46. package/src/_api/generated/cfg_monitor/schemas/LevelEnum.ts +9 -0
  47. package/src/_api/generated/cfg_monitor/schemas/index.ts +7 -0
  48. package/src/_api/generated/cfg_monitor/sdk.gen.ts +55 -0
  49. package/src/_api/generated/cfg_monitor/types.gen.ts +79 -0
  50. package/src/_api/generated/index.ts +22 -0
  51. package/src/_api/index.ts +2 -2
  52. package/src/client/capture/console.ts +2 -3
  53. package/src/client/transport/ingest.ts +21 -17
  54. package/src/server/index.ts +3 -2
  55. package/src/_api/generated/cfg_monitor/CLAUDE.md +0 -60
  56. package/src/_api/generated/cfg_monitor/_utils/fetchers/index.ts +0 -30
  57. package/src/_api/generated/cfg_monitor/_utils/fetchers/monitor.ts +0 -51
  58. package/src/_api/generated/cfg_monitor/_utils/hooks/index.ts +0 -30
  59. package/src/_api/generated/cfg_monitor/_utils/hooks/monitor.ts +0 -43
  60. package/src/_api/generated/cfg_monitor/_utils/schemas/IngestBatchRequest.schema.ts +0 -20
  61. package/src/_api/generated/cfg_monitor/_utils/schemas/index.ts +0 -22
  62. package/src/_api/generated/cfg_monitor/api-instance.ts +0 -181
  63. package/src/_api/generated/cfg_monitor/client.ts +0 -330
  64. package/src/_api/generated/cfg_monitor/enums.ts +0 -34
  65. package/src/_api/generated/cfg_monitor/errors.ts +0 -123
  66. package/src/_api/generated/cfg_monitor/http.ts +0 -160
  67. package/src/_api/generated/cfg_monitor/logger.ts +0 -261
  68. package/src/_api/generated/cfg_monitor/monitor/client.ts +0 -26
  69. package/src/_api/generated/cfg_monitor/monitor/index.ts +0 -4
  70. package/src/_api/generated/cfg_monitor/monitor/models.ts +0 -47
  71. package/src/_api/generated/cfg_monitor/retry.ts +0 -177
  72. package/src/_api/generated/cfg_monitor/schema.json +0 -181
  73. package/src/_api/generated/cfg_monitor/storage.ts +0 -163
  74. package/src/_api/generated/cfg_monitor/validation-events.ts +0 -135
@@ -0,0 +1,123 @@
1
+ // AUTO-GENERATED by django_generator / ts_extras.wrapper
2
+ // API logger built on consola. Optional dependency — install if you enable logging:
3
+ // npm install consola
4
+ // DO NOT EDIT — re-run `make gen`.
5
+
6
+ import { type ConsolaInstance, createConsola } from "consola";
7
+
8
+ export interface RequestLog {
9
+ method: string;
10
+ url: string;
11
+ headers?: Record<string, string>;
12
+ body?: any;
13
+ timestamp: number;
14
+ }
15
+
16
+ export interface ResponseLog {
17
+ status: number;
18
+ statusText: string;
19
+ data?: any;
20
+ duration: number;
21
+ timestamp: number;
22
+ }
23
+
24
+ export interface ErrorLog {
25
+ message: string;
26
+ statusCode?: number;
27
+ fieldErrors?: Record<string, string[]>;
28
+ duration: number;
29
+ timestamp: number;
30
+ }
31
+
32
+ export interface LoggerConfig {
33
+ enabled: boolean;
34
+ logRequests: boolean;
35
+ logResponses: boolean;
36
+ logErrors: boolean;
37
+ logBodies: boolean;
38
+ logHeaders: boolean;
39
+ consola?: ConsolaInstance;
40
+ }
41
+
42
+ const DEFAULT_CONFIG: LoggerConfig = {
43
+ enabled: typeof process !== "undefined" && process.env?.NODE_ENV !== "production",
44
+ logRequests: true,
45
+ logResponses: true,
46
+ logErrors: true,
47
+ logBodies: true,
48
+ logHeaders: false,
49
+ };
50
+
51
+ const SENSITIVE_HEADERS = [
52
+ "authorization",
53
+ "cookie",
54
+ "set-cookie",
55
+ "x-api-key",
56
+ "x-csrf-token",
57
+ ];
58
+
59
+ export class APILogger {
60
+ private config: LoggerConfig;
61
+ private consola: ConsolaInstance;
62
+
63
+ constructor(config: Partial<LoggerConfig> = {}) {
64
+ this.config = { ...DEFAULT_CONFIG, ...config };
65
+ this.consola = config.consola || createConsola({
66
+ level: this.config.enabled ? 4 : 0,
67
+ });
68
+ }
69
+
70
+ enable(): void { this.config.enabled = true; }
71
+ disable(): void { this.config.enabled = false; }
72
+ setConfig(config: Partial<LoggerConfig>): void {
73
+ this.config = { ...this.config, ...config };
74
+ }
75
+
76
+ private filterHeaders(headers?: Record<string, string>): Record<string, string> {
77
+ if (!headers) return {};
78
+ const filtered: Record<string, string> = {};
79
+ Object.keys(headers).forEach((key) => {
80
+ filtered[key] = SENSITIVE_HEADERS.includes(key.toLowerCase()) ? "***" : (headers[key] || "");
81
+ });
82
+ return filtered;
83
+ }
84
+
85
+ logRequest(request: RequestLog): void {
86
+ if (!this.config.enabled || !this.config.logRequests) return;
87
+ const { method, url, headers, body } = request;
88
+ this.consola.start(`${method} ${url}`);
89
+ if (this.config.logHeaders && headers) this.consola.debug("Headers:", this.filterHeaders(headers));
90
+ if (this.config.logBodies && body) this.consola.debug("Body:", body);
91
+ }
92
+
93
+ logResponse(request: RequestLog, response: ResponseLog): void {
94
+ if (!this.config.enabled || !this.config.logResponses) return;
95
+ const { method, url } = request;
96
+ const { status, statusText, data, duration } = response;
97
+ this.consola.success(`${method} ${url} ${status} ${statusText} (${duration}ms)`);
98
+ if (this.config.logBodies && data) this.consola.debug("Response:", data);
99
+ }
100
+
101
+ logError(request: RequestLog, error: ErrorLog): void {
102
+ if (!this.config.enabled || !this.config.logErrors) return;
103
+ const { method, url } = request;
104
+ const { message, statusCode, fieldErrors, duration } = error;
105
+ this.consola.error(`${method} ${url} ${statusCode || "Network"} Error (${duration}ms)`);
106
+ this.consola.error("Message:", message);
107
+ if (fieldErrors && Object.keys(fieldErrors).length > 0) {
108
+ this.consola.error("Field Errors:");
109
+ Object.entries(fieldErrors).forEach(([field, errors]) => {
110
+ errors.forEach((err) => this.consola.error(` • ${field}: ${err}`));
111
+ });
112
+ }
113
+ }
114
+
115
+ info(message: string, ...args: any[]): void { if (this.config.enabled) this.consola.info(message, ...args); }
116
+ warn(message: string, ...args: any[]): void { if (this.config.enabled) this.consola.warn(message, ...args); }
117
+ error(message: string, ...args: any[]): void { if (this.config.enabled) this.consola.error(message, ...args); }
118
+ debug(message: string, ...args: any[]): void { if (this.config.enabled) this.consola.debug(message, ...args); }
119
+ success(message: string, ...args: any[]): void { if (this.config.enabled) this.consola.success(message, ...args); }
120
+ withTag(tag: string): ConsolaInstance { return this.consola.withTag(tag); }
121
+ }
122
+
123
+ export const defaultLogger = new APILogger();
@@ -0,0 +1,83 @@
1
+ // AUTO-GENERATED by django_generator / ts_extras.wrapper
2
+ // Storage adapters for token persistence.
3
+ // DO NOT EDIT — re-run `make gen`.
4
+
5
+ export interface StorageAdapter {
6
+ getItem(key: string): string | null;
7
+ setItem(key: string, value: string): void;
8
+ removeItem(key: string): void;
9
+ clear?(): void;
10
+ }
11
+
12
+ /** Browser localStorage. Falls back to no-op on SSR / private mode. */
13
+ export class LocalStorageAdapter implements StorageAdapter {
14
+ getItem(key: string): string | null {
15
+ if (typeof window === "undefined") return null;
16
+ try { return window.localStorage.getItem(key); } catch { return null; }
17
+ }
18
+ setItem(key: string, value: string): void {
19
+ if (typeof window === "undefined") return;
20
+ try { window.localStorage.setItem(key, value); } catch { /* quota / private */ }
21
+ }
22
+ removeItem(key: string): void {
23
+ if (typeof window === "undefined") return;
24
+ try { window.localStorage.removeItem(key); } catch { /* ignore */ }
25
+ }
26
+ clear(): void {
27
+ if (typeof window === "undefined") return;
28
+ try { window.localStorage.clear(); } catch { /* ignore */ }
29
+ }
30
+ }
31
+
32
+ /** In-memory store. Use for SSR, Electron main process, or tests. */
33
+ export class MemoryStorageAdapter implements StorageAdapter {
34
+ private store = new Map<string, string>();
35
+ getItem(key: string): string | null { return this.store.get(key) ?? null; }
36
+ setItem(key: string, value: string): void { this.store.set(key, value); }
37
+ removeItem(key: string): void { this.store.delete(key); }
38
+ clear(): void { this.store.clear(); }
39
+ }
40
+
41
+ /** Cookie-backed storage (browser only). */
42
+ export class CookieStorageAdapter implements StorageAdapter {
43
+ constructor(
44
+ private opts: {
45
+ domain?: string;
46
+ path?: string;
47
+ secure?: boolean;
48
+ sameSite?: "Strict" | "Lax" | "None";
49
+ maxAgeSeconds?: number;
50
+ } = {},
51
+ ) {}
52
+
53
+ getItem(key: string): string | null {
54
+ if (typeof document === "undefined") return null;
55
+ const prefix = `${encodeURIComponent(key)}=`;
56
+ for (const part of document.cookie.split("; ")) {
57
+ if (part.startsWith(prefix)) {
58
+ return decodeURIComponent(part.slice(prefix.length));
59
+ }
60
+ }
61
+ return null;
62
+ }
63
+
64
+ setItem(key: string, value: string): void {
65
+ if (typeof document === "undefined") return;
66
+ const parts = [
67
+ `${encodeURIComponent(key)}=${encodeURIComponent(value)}`,
68
+ `Path=${this.opts.path ?? "/"}`,
69
+ ];
70
+ if (this.opts.domain) parts.push(`Domain=${this.opts.domain}`);
71
+ if (this.opts.secure) parts.push("Secure");
72
+ if (this.opts.sameSite) parts.push(`SameSite=${this.opts.sameSite}`);
73
+ if (this.opts.maxAgeSeconds != null) {
74
+ parts.push(`Max-Age=${this.opts.maxAgeSeconds}`);
75
+ }
76
+ document.cookie = parts.join("; ");
77
+ }
78
+
79
+ removeItem(key: string): void {
80
+ if (typeof document === "undefined") return;
81
+ document.cookie = `${encodeURIComponent(key)}=; Max-Age=0; Path=${this.opts.path ?? "/"}`;
82
+ }
83
+ }
@@ -0,0 +1,52 @@
1
+ // AUTO-GENERATED by django_generator / ts_extras.wrapper
2
+ // Browser CustomEvent integration for Zod validation errors.
3
+ // DO NOT EDIT — re-run `make gen`.
4
+
5
+ import type { ZodError } from "zod";
6
+
7
+ export interface ValidationErrorDetail {
8
+ operation: string;
9
+ path: string;
10
+ method: string;
11
+ error: ZodError;
12
+ response: any;
13
+ timestamp: Date;
14
+ }
15
+
16
+ export type ValidationErrorEvent = CustomEvent<ValidationErrorDetail>;
17
+
18
+ export function dispatchValidationError(detail: ValidationErrorDetail): void {
19
+ if (typeof window === "undefined") return;
20
+ try {
21
+ const event = new CustomEvent<ValidationErrorDetail>("zod-validation-error", {
22
+ detail,
23
+ bubbles: true,
24
+ cancelable: false,
25
+ });
26
+ window.dispatchEvent(event);
27
+ } catch (error) {
28
+ console.warn("Failed to dispatch validation error event:", error);
29
+ }
30
+ }
31
+
32
+ export function onValidationError(
33
+ callback: (detail: ValidationErrorDetail) => void,
34
+ ): () => void {
35
+ if (typeof window === "undefined") return () => {};
36
+ const handler = (event: Event) => {
37
+ if (event instanceof CustomEvent) callback(event.detail);
38
+ };
39
+ window.addEventListener("zod-validation-error", handler);
40
+ return () => window.removeEventListener("zod-validation-error", handler);
41
+ }
42
+
43
+ export function formatZodError(error: ZodError): string {
44
+ const issues = error.issues.map((issue, index) => {
45
+ const path = issue.path.join(".") || "root";
46
+ const parts = [`${index + 1}. ${path}: ${issue.message}`];
47
+ if ("expected" in issue && issue.expected) parts.push(` Expected: ${issue.expected}`);
48
+ if ("received" in issue && issue.received) parts.push(` Received: ${issue.received}`);
49
+ return parts.join("\n");
50
+ });
51
+ return issues.join("\n");
52
+ }
@@ -0,0 +1,122 @@
1
+ // AUTO-GENERATED by django_generator / ts_extras.wrapper
2
+ // Self-contained API wrapper for this group. DO NOT EDIT — re-run `make gen`.
3
+
4
+ import { client } from './client.gen';
5
+ import type { StorageAdapter } from '../_shared/storage';
6
+ import { LocalStorageAdapter } from '../_shared/storage';
7
+ import { APILogger, type LoggerConfig } from '../_shared/logger';
8
+
9
+ import { Cfg } from './sdk.gen';
10
+ import { Monitor } from './sdk.gen';
11
+
12
+
13
+ const ACCESS_KEY = 'cfg.access_token';
14
+ const REFRESH_KEY = 'cfg.refresh_token';
15
+
16
+
17
+
18
+ /** Auto-detect locale from cookie NEXT_LOCALE or navigator.language. */
19
+ function detectLocale(): string | null {
20
+ try {
21
+ if (typeof document !== 'undefined') {
22
+ const m = document.cookie.match(/(?:^|;\s*)NEXT_LOCALE=([^;]*)/);
23
+ if (m) return decodeURIComponent(m[1]);
24
+ }
25
+ if (typeof navigator !== 'undefined' && navigator.language) {
26
+ return navigator.language;
27
+ }
28
+ } catch {}
29
+ return null;
30
+ }
31
+
32
+ export interface APIOptions {
33
+ /** Override storage backend (LocalStorage by default; Memory for SSR/tests). */
34
+ storage?: StorageAdapter;
35
+ /** Logger config (defaults to dev-only). */
36
+ logger?: Partial<LoggerConfig>;
37
+ /** Locale for `Accept-Language`. If omitted, auto-detected from cookie/navigator. */
38
+ locale?: string;
39
+ /** API key sent as `X-API-Key`. Falls back to NEXT_PUBLIC_API_KEY. */
40
+ apiKey?: string;
41
+ /** Send Django session/CSRF cookies cross-origin. Defaults to true. */
42
+ withCredentials?: boolean;
43
+ }
44
+
45
+ /**
46
+ * Self-contained API wrapper for this group.
47
+ *
48
+ * Each group has its own client + interceptor + token store. The interceptor
49
+ * automatically attaches:
50
+ * - `Authorization: Bearer <jwt>` from storage
51
+ * - `Accept-Language` from `opts.locale` or `NEXT_LOCALE` cookie
52
+ * - `X-API-Key` from `opts.apiKey` or `NEXT_PUBLIC_API_KEY`
53
+ * - `credentials: 'include'` for Django session/CSRF cookies (toggle via opts)
54
+ */
55
+ export class API {
56
+ private baseUrl: string;
57
+ private storage: StorageAdapter;
58
+ private locale: string | null;
59
+ private apiKey: string | null;
60
+ readonly logger: APILogger;
61
+
62
+ readonly cfg = Cfg;
63
+ readonly monitor = Monitor;
64
+
65
+ constructor(baseUrl: string, opts: APIOptions = {}) {
66
+ this.baseUrl = baseUrl.replace(/\/$/, '');
67
+ this.storage = opts.storage ?? new LocalStorageAdapter();
68
+ this.logger = new APILogger(opts.logger);
69
+ this.locale = opts.locale ?? null;
70
+ this.apiKey = opts.apiKey ?? (typeof process !== 'undefined' ? (process.env?.NEXT_PUBLIC_API_KEY ?? null) : null);
71
+
72
+ const credentials: RequestCredentials = (opts.withCredentials ?? true) ? 'include' : 'same-origin';
73
+ client.setConfig({ baseUrl: this.baseUrl, credentials });
74
+
75
+ client.interceptors.request.use((request) => {
76
+ const access = this.getToken();
77
+ if (access) request.headers.set('Authorization', `Bearer ${access}`);
78
+
79
+ const locale = this.locale ?? detectLocale();
80
+ if (locale) request.headers.set('Accept-Language', locale);
81
+
82
+ if (this.apiKey) request.headers.set('X-API-Key', this.apiKey);
83
+
84
+ return request;
85
+ });
86
+
87
+
88
+ }
89
+
90
+ // ── Base URL ────────────────────────────────────────────────────────────
91
+ getBaseUrl(): string { return this.baseUrl; }
92
+ setBaseUrl(url: string): void {
93
+ this.baseUrl = url.replace(/\/$/, '');
94
+ client.setConfig({ baseUrl: this.baseUrl });
95
+ }
96
+
97
+ // ── Tokens ──────────────────────────────────────────────────────────────
98
+ getToken(): string | null { return this.storage.getItem(ACCESS_KEY); }
99
+ setToken(token: string | null): void {
100
+ if (token) this.storage.setItem(ACCESS_KEY, token);
101
+ else this.storage.removeItem(ACCESS_KEY);
102
+ }
103
+ getRefreshToken(): string | null { return this.storage.getItem(REFRESH_KEY); }
104
+ setRefreshToken(token: string | null): void {
105
+ if (token) this.storage.setItem(REFRESH_KEY, token);
106
+ else this.storage.removeItem(REFRESH_KEY);
107
+ }
108
+ clearToken(): void {
109
+ this.storage.removeItem(ACCESS_KEY);
110
+ this.storage.removeItem(REFRESH_KEY);
111
+ }
112
+ isAuthenticated(): boolean { return this.getToken() !== null; }
113
+
114
+ // ── Locale / API key ────────────────────────────────────────────────────
115
+ getLocale(): string | null { return this.locale ?? detectLocale(); }
116
+ setLocale(locale: string | null): void { this.locale = locale; }
117
+ getApiKey(): string | null { return this.apiKey; }
118
+ setApiKey(key: string | null): void { this.apiKey = key; }
119
+ }
120
+
121
+ export { Cfg, Monitor };
122
+ export { client };
@@ -0,0 +1,280 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ import { createSseClient } from '../core/serverSentEvents.gen';
4
+ import type { HttpMethod } from '../core/types.gen';
5
+ import { getValidRequestBody } from '../core/utils.gen';
6
+ import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';
7
+ import {
8
+ buildUrl,
9
+ createConfig,
10
+ createInterceptors,
11
+ getParseAs,
12
+ mergeConfigs,
13
+ mergeHeaders,
14
+ setAuthParams,
15
+ } from './utils.gen';
16
+
17
+ type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
18
+ body?: any;
19
+ headers: ReturnType<typeof mergeHeaders>;
20
+ };
21
+
22
+ export const createClient = (config: Config = {}): Client => {
23
+ let _config = mergeConfigs(createConfig(), config);
24
+
25
+ const getConfig = (): Config => ({ ..._config });
26
+
27
+ const setConfig = (config: Config): Config => {
28
+ _config = mergeConfigs(_config, config);
29
+ return getConfig();
30
+ };
31
+
32
+ const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();
33
+
34
+ const beforeRequest = async <
35
+ TData = unknown,
36
+ TResponseStyle extends 'data' | 'fields' = 'fields',
37
+ ThrowOnError extends boolean = boolean,
38
+ Url extends string = string,
39
+ >(
40
+ options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
41
+ ) => {
42
+ const opts = {
43
+ ..._config,
44
+ ...options,
45
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
46
+ headers: mergeHeaders(_config.headers, options.headers),
47
+ serializedBody: undefined as string | undefined,
48
+ };
49
+
50
+ if (opts.security) {
51
+ await setAuthParams({
52
+ ...opts,
53
+ security: opts.security,
54
+ });
55
+ }
56
+
57
+ if (opts.requestValidator) {
58
+ await opts.requestValidator(opts);
59
+ }
60
+
61
+ if (opts.body !== undefined && opts.bodySerializer) {
62
+ opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined;
63
+ }
64
+
65
+ // remove Content-Type header if body is empty to avoid sending invalid requests
66
+ if (opts.body === undefined || opts.serializedBody === '') {
67
+ opts.headers.delete('Content-Type');
68
+ }
69
+
70
+ const resolvedOpts = opts as typeof opts &
71
+ ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;
72
+ const url = buildUrl(resolvedOpts);
73
+
74
+ return { opts: resolvedOpts, url };
75
+ };
76
+
77
+ const request: Client['request'] = async (options) => {
78
+ const throwOnError = options.throwOnError ?? _config.throwOnError;
79
+ const responseStyle = options.responseStyle ?? _config.responseStyle;
80
+
81
+ let request: Request | undefined;
82
+ let response: Response | undefined;
83
+
84
+ try {
85
+ const { opts, url } = await beforeRequest(options);
86
+ const requestInit: ReqInit = {
87
+ redirect: 'follow',
88
+ ...opts,
89
+ body: getValidRequestBody(opts),
90
+ };
91
+
92
+ request = new Request(url, requestInit);
93
+
94
+ for (const fn of interceptors.request.fns) {
95
+ if (fn) {
96
+ request = await fn(request, opts);
97
+ }
98
+ }
99
+
100
+ // fetch must be assigned here, otherwise it would throw the error:
101
+ // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
102
+ const _fetch = opts.fetch!;
103
+
104
+ response = await _fetch(request);
105
+
106
+ for (const fn of interceptors.response.fns) {
107
+ if (fn) {
108
+ response = await fn(response, request, opts);
109
+ }
110
+ }
111
+
112
+ const result = {
113
+ request,
114
+ response,
115
+ };
116
+
117
+ if (response.ok) {
118
+ const parseAs =
119
+ (opts.parseAs === 'auto'
120
+ ? getParseAs(response.headers.get('Content-Type'))
121
+ : opts.parseAs) ?? 'json';
122
+
123
+ if (response.status === 204 || response.headers.get('Content-Length') === '0') {
124
+ let emptyData: any;
125
+ switch (parseAs) {
126
+ case 'arrayBuffer':
127
+ case 'blob':
128
+ case 'text':
129
+ emptyData = await response[parseAs]();
130
+ break;
131
+ case 'formData':
132
+ emptyData = new FormData();
133
+ break;
134
+ case 'stream':
135
+ emptyData = response.body;
136
+ break;
137
+ case 'json':
138
+ default:
139
+ emptyData = {};
140
+ break;
141
+ }
142
+ return opts.responseStyle === 'data'
143
+ ? emptyData
144
+ : {
145
+ data: emptyData,
146
+ ...result,
147
+ };
148
+ }
149
+
150
+ let data: any;
151
+ switch (parseAs) {
152
+ case 'arrayBuffer':
153
+ case 'blob':
154
+ case 'formData':
155
+ case 'text':
156
+ data = await response[parseAs]();
157
+ break;
158
+ case 'json': {
159
+ // Some servers return 200 with no Content-Length and empty body.
160
+ // response.json() would throw; read as text and parse if non-empty.
161
+ const text = await response.text();
162
+ data = text ? JSON.parse(text) : {};
163
+ break;
164
+ }
165
+ case 'stream':
166
+ return opts.responseStyle === 'data'
167
+ ? response.body
168
+ : {
169
+ data: response.body,
170
+ ...result,
171
+ };
172
+ }
173
+
174
+ if (parseAs === 'json') {
175
+ if (opts.responseValidator) {
176
+ await opts.responseValidator(data);
177
+ }
178
+
179
+ if (opts.responseTransformer) {
180
+ data = await opts.responseTransformer(data);
181
+ }
182
+ }
183
+
184
+ return opts.responseStyle === 'data'
185
+ ? data
186
+ : {
187
+ data,
188
+ ...result,
189
+ };
190
+ }
191
+
192
+ const textError = await response.text();
193
+ let jsonError: unknown;
194
+
195
+ try {
196
+ jsonError = JSON.parse(textError);
197
+ } catch {
198
+ // noop
199
+ }
200
+
201
+ throw jsonError ?? textError;
202
+ } catch (error) {
203
+ let finalError = error;
204
+
205
+ for (const fn of interceptors.error.fns) {
206
+ if (fn) {
207
+ finalError = await fn(finalError, response, request, options as ResolvedRequestOptions);
208
+ }
209
+ }
210
+
211
+ finalError = finalError || {};
212
+
213
+ if (throwOnError) {
214
+ throw finalError;
215
+ }
216
+
217
+ // TODO: we probably want to return error and improve types
218
+ return responseStyle === 'data'
219
+ ? undefined
220
+ : {
221
+ error: finalError,
222
+ request,
223
+ response,
224
+ };
225
+ }
226
+ };
227
+
228
+ const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
229
+ request({ ...options, method });
230
+
231
+ const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
232
+ const { opts, url } = await beforeRequest(options);
233
+ return createSseClient({
234
+ ...opts,
235
+ body: opts.body as BodyInit | null | undefined,
236
+ method,
237
+ onRequest: async (url, init) => {
238
+ let request = new Request(url, init);
239
+ for (const fn of interceptors.request.fns) {
240
+ if (fn) {
241
+ request = await fn(request, opts);
242
+ }
243
+ }
244
+ return request;
245
+ },
246
+ serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined,
247
+ url,
248
+ });
249
+ };
250
+
251
+ const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options });
252
+
253
+ return {
254
+ buildUrl: _buildUrl,
255
+ connect: makeMethodFn('CONNECT'),
256
+ delete: makeMethodFn('DELETE'),
257
+ get: makeMethodFn('GET'),
258
+ getConfig,
259
+ head: makeMethodFn('HEAD'),
260
+ interceptors,
261
+ options: makeMethodFn('OPTIONS'),
262
+ patch: makeMethodFn('PATCH'),
263
+ post: makeMethodFn('POST'),
264
+ put: makeMethodFn('PUT'),
265
+ request,
266
+ setConfig,
267
+ sse: {
268
+ connect: makeSseFn('CONNECT'),
269
+ delete: makeSseFn('DELETE'),
270
+ get: makeSseFn('GET'),
271
+ head: makeSseFn('HEAD'),
272
+ options: makeSseFn('OPTIONS'),
273
+ patch: makeSseFn('PATCH'),
274
+ post: makeSseFn('POST'),
275
+ put: makeSseFn('PUT'),
276
+ trace: makeSseFn('TRACE'),
277
+ },
278
+ trace: makeMethodFn('TRACE'),
279
+ } as Client;
280
+ };
@@ -0,0 +1,25 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ export type { Auth } from '../core/auth.gen';
4
+ export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
5
+ export {
6
+ formDataBodySerializer,
7
+ jsonBodySerializer,
8
+ urlSearchParamsBodySerializer,
9
+ } from '../core/bodySerializer.gen';
10
+ export { buildClientParams } from '../core/params.gen';
11
+ export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
12
+ export { createClient } from './client.gen';
13
+ export type {
14
+ Client,
15
+ ClientOptions,
16
+ Config,
17
+ CreateClientConfig,
18
+ Options,
19
+ RequestOptions,
20
+ RequestResult,
21
+ ResolvedRequestOptions,
22
+ ResponseStyle,
23
+ TDataShape,
24
+ } from './types.gen';
25
+ export { createConfig, mergeHeaders } from './utils.gen';