@vibesdotdev/client 0.1.1 → 1.0.0-rc.3
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/LICENSE +21 -0
- package/README.md +24 -15
- package/dist/api-client-plugin.d.ts +4 -0
- package/dist/api-client-plugin.d.ts.map +1 -0
- package/dist/api-client-plugin.js +20 -0
- package/dist/api-client-plugin.js.map +1 -0
- package/dist/api-client.impl.d.ts +23 -0
- package/dist/api-client.impl.d.ts.map +1 -0
- package/dist/api-client.impl.js +47 -0
- package/dist/api-client.impl.js.map +1 -0
- package/dist/client.consumer.plugin.d.ts +3 -0
- package/dist/client.consumer.plugin.d.ts.map +1 -0
- package/dist/client.consumer.plugin.js +10 -0
- package/dist/client.consumer.plugin.js.map +1 -0
- package/dist/cloud.plugin.d.ts +3 -0
- package/dist/cloud.plugin.d.ts.map +1 -0
- package/dist/cloud.plugin.js +10 -0
- package/dist/cloud.plugin.js.map +1 -0
- package/dist/config/client.config.descriptor.d.ts +4 -0
- package/dist/config/client.config.descriptor.d.ts.map +1 -0
- package/dist/config/client.config.descriptor.js +32 -0
- package/dist/config/client.config.descriptor.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/settings.d.ts +9 -0
- package/dist/config/settings.d.ts.map +1 -0
- package/dist/config/settings.js +25 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/docs/client.api-request.docs.descriptor.d.ts +4 -0
- package/dist/docs/client.api-request.docs.descriptor.d.ts.map +1 -0
- package/dist/docs/client.api-request.docs.descriptor.js +71 -0
- package/dist/docs/client.api-request.docs.descriptor.js.map +1 -0
- package/dist/events/auth-rejected.event.d.ts +35 -0
- package/dist/events/auth-rejected.event.d.ts.map +1 -0
- package/dist/events/auth-rejected.event.js +36 -0
- package/dist/events/auth-rejected.event.js.map +1 -0
- package/dist/factory.d.ts +5 -1
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +16 -17
- package/dist/factory.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/kind-augment.d.ts +11 -0
- package/dist/kind-augment.d.ts.map +1 -0
- package/dist/kind-augment.js +2 -0
- package/dist/kind-augment.js.map +1 -0
- package/dist/lib/client/api-diagnostics.d.ts +79 -0
- package/dist/lib/client/api-diagnostics.d.ts.map +1 -0
- package/dist/lib/client/api-diagnostics.js +111 -0
- package/dist/lib/client/api-diagnostics.js.map +1 -0
- package/dist/lib/client/configured.d.ts +78 -0
- package/dist/lib/client/configured.d.ts.map +1 -0
- package/dist/lib/client/configured.js +261 -0
- package/dist/lib/client/configured.js.map +1 -0
- package/dist/lib/client/internal/auth-headers.d.ts +11 -0
- package/dist/lib/client/internal/auth-headers.d.ts.map +1 -0
- package/dist/lib/client/internal/auth-headers.js +35 -0
- package/dist/lib/client/internal/auth-headers.js.map +1 -0
- package/dist/lib/client/internal/base-client.d.ts +5 -2
- package/dist/lib/client/internal/base-client.d.ts.map +1 -1
- package/dist/lib/client/internal/base-client.js +42 -22
- package/dist/lib/client/internal/base-client.js.map +1 -1
- package/dist/lib/client/internal/base-helpers.d.ts.map +1 -1
- package/dist/lib/client/internal/base-helpers.js +20 -20
- package/dist/lib/client/internal/base-helpers.js.map +1 -1
- package/dist/lib/client/internal/base-types.d.ts +10 -5
- package/dist/lib/client/internal/base-types.d.ts.map +1 -1
- package/dist/lib/client/internal/base-types.js +5 -3
- package/dist/lib/client/internal/base-types.js.map +1 -1
- package/dist/lib/client/internal/client-values.d.ts +43 -0
- package/dist/lib/client/internal/client-values.d.ts.map +1 -0
- package/dist/lib/client/internal/client-values.js +76 -0
- package/dist/lib/client/internal/client-values.js.map +1 -0
- package/dist/lib/client/internal/endpoint.d.ts +6 -5
- package/dist/lib/client/internal/endpoint.d.ts.map +1 -1
- package/dist/lib/client/internal/endpoint.js +3 -0
- package/dist/lib/client/internal/endpoint.js.map +1 -1
- package/dist/lib/client/internal/generator.d.ts +98 -9
- package/dist/lib/client/internal/generator.d.ts.map +1 -1
- package/dist/lib/client/internal/generator.js +92 -140
- package/dist/lib/client/internal/generator.js.map +1 -1
- package/dist/lib/client/internal/request-builder.d.ts +5 -2
- package/dist/lib/client/internal/request-builder.d.ts.map +1 -1
- package/dist/lib/client/internal/request-builder.js +105 -65
- package/dist/lib/client/internal/request-builder.js.map +1 -1
- package/dist/lib/client/internal/sse-stream.d.ts +9 -5
- package/dist/lib/client/internal/sse-stream.d.ts.map +1 -1
- package/dist/lib/client/internal/sse-stream.js +96 -94
- package/dist/lib/client/internal/sse-stream.js.map +1 -1
- package/dist/lib/client/internal/timeout-signal.d.ts +8 -0
- package/dist/lib/client/internal/timeout-signal.d.ts.map +1 -0
- package/dist/lib/client/internal/timeout-signal.js +17 -0
- package/dist/lib/client/internal/timeout-signal.js.map +1 -0
- package/dist/lib/client/internal/transport/http2-fetch.d.ts +8 -0
- package/dist/lib/client/internal/transport/http2-fetch.d.ts.map +1 -0
- package/dist/lib/client/internal/transport/http2-fetch.js +17 -0
- package/dist/lib/client/internal/transport/http2-fetch.js.map +1 -0
- package/dist/lib/client/internal/vibes-client.d.ts +17 -8
- package/dist/lib/client/internal/vibes-client.d.ts.map +1 -1
- package/dist/lib/client/internal/vibes-client.js +127 -67
- package/dist/lib/client/internal/vibes-client.js.map +1 -1
- package/dist/lib/client/internal/wrap-fetch.d.ts +3 -2
- package/dist/lib/client/internal/wrap-fetch.d.ts.map +1 -1
- package/dist/lib/client/internal/wrap-fetch.js +14 -33
- package/dist/lib/client/internal/wrap-fetch.js.map +1 -1
- package/dist/lib/client/runtime-fetch.d.ts +14 -0
- package/dist/lib/client/runtime-fetch.d.ts.map +1 -0
- package/dist/lib/client/runtime-fetch.js +25 -0
- package/dist/lib/client/runtime-fetch.js.map +1 -0
- package/dist/lib/client/types.d.ts +18 -9
- package/dist/lib/client/types.d.ts.map +1 -1
- package/dist/lib/client/types.js +22 -3
- package/dist/lib/client/types.js.map +1 -1
- package/dist/plugin.d.ts +2 -18
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +7 -74
- package/dist/plugin.js.map +1 -1
- package/dist/runtime-client.d.ts +10 -0
- package/dist/runtime-client.d.ts.map +1 -0
- package/dist/runtime-client.js +14 -0
- package/dist/runtime-client.js.map +1 -0
- package/dist/schemas/auth-rejected.d.ts +12 -0
- package/dist/schemas/auth-rejected.d.ts.map +1 -0
- package/dist/schemas/auth-rejected.js +11 -0
- package/dist/schemas/auth-rejected.js.map +1 -0
- package/dist/schemas/sdk-languages.d.ts +47 -0
- package/dist/schemas/sdk-languages.d.ts.map +1 -0
- package/dist/schemas/sdk-languages.js +75 -0
- package/dist/schemas/sdk-languages.js.map +1 -0
- package/dist/schemas/settings.d.ts +14 -0
- package/dist/schemas/settings.d.ts.map +1 -0
- package/dist/schemas/settings.js +10 -0
- package/dist/schemas/settings.js.map +1 -0
- package/dist/schemas/validated-request.d.ts +19 -0
- package/dist/schemas/validated-request.d.ts.map +1 -0
- package/dist/schemas/validated-request.js +2 -0
- package/dist/schemas/validated-request.js.map +1 -0
- package/dist/schemas.d.ts +23 -8
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +8 -2
- package/dist/schemas.js.map +1 -1
- package/dist/sse-client.d.ts +17 -15
- package/dist/sse-client.d.ts.map +1 -1
- package/dist/sse-client.js +111 -91
- package/dist/sse-client.js.map +1 -1
- package/dist/svelte/client-svelte.plugin.d.ts +5 -0
- package/dist/svelte/client-svelte.plugin.d.ts.map +1 -0
- package/dist/svelte/client-svelte.plugin.js +46 -0
- package/dist/svelte/index.d.ts +3 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +2 -0
- package/dist/svelte/styles.css +8 -0
- package/dist/svelte/tool-widgets/ApiRequestToolCard.svelte +53 -0
- package/dist/svelte/tool-widgets/ApiRequestToolCard.svelte.d.ts +5 -0
- package/dist/svelte/tool-widgets/ApiRequestToolCard.svelte.d.ts.map +1 -0
- package/dist/svelte/tool-widgets/index.d.ts +2 -0
- package/dist/svelte/tool-widgets/index.d.ts.map +1 -0
- package/dist/svelte/tool-widgets/index.js +1 -0
- package/dist/tools/api-request/api-request.contract.d.ts +19 -0
- package/dist/tools/api-request/api-request.contract.d.ts.map +1 -0
- package/dist/tools/api-request/api-request.contract.js +110 -0
- package/dist/tools/api-request/api-request.contract.js.map +1 -0
- package/dist/tools/api-request/api-request.descriptor.d.ts +11 -4
- package/dist/tools/api-request/api-request.descriptor.d.ts.map +1 -1
- package/dist/tools/api-request/api-request.descriptor.js +8 -5
- package/dist/tools/api-request/api-request.descriptor.js.map +1 -1
- package/dist/tools/api-request/api-request.impl.cloud.d.ts +15 -0
- package/dist/tools/api-request/api-request.impl.cloud.d.ts.map +1 -0
- package/dist/tools/api-request/api-request.impl.cloud.js +75 -0
- package/dist/tools/api-request/api-request.impl.cloud.js.map +1 -0
- package/dist/tools/api-request/api-request.impl.consumer.d.ts +5 -3
- package/dist/tools/api-request/api-request.impl.consumer.d.ts.map +1 -1
- package/dist/tools/api-request/api-request.impl.consumer.js +27 -33
- package/dist/tools/api-request/api-request.impl.consumer.js.map +1 -1
- package/dist/tools/api-request/api-request.view.d.ts +29 -0
- package/dist/tools/api-request/api-request.view.d.ts.map +1 -0
- package/dist/tools/api-request/api-request.view.js +62 -0
- package/dist/tools/api-request/api-request.view.js.map +1 -0
- package/dist/tools/api-request/schemas/index.d.ts +12 -5
- package/dist/tools/api-request/schemas/index.d.ts.map +1 -1
- package/dist/tools/api-request/schemas/index.js +24 -6
- package/dist/tools/api-request/schemas/index.js.map +1 -1
- package/dist/tui/client-tui.plugin.d.ts +3 -0
- package/dist/tui/client-tui.plugin.d.ts.map +1 -0
- package/dist/tui/client-tui.plugin.js +32 -0
- package/dist/tui/client-tui.plugin.js.map +1 -0
- package/dist/tui/index.d.ts +2 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +2 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/tool-widgets/ApiRequestToolWidget.impl.tui.d.ts +17 -0
- package/dist/tui/tool-widgets/ApiRequestToolWidget.impl.tui.d.ts.map +1 -0
- package/dist/tui/tool-widgets/ApiRequestToolWidget.impl.tui.js +28 -0
- package/dist/tui/tool-widgets/ApiRequestToolWidget.impl.tui.js.map +1 -0
- package/dist/validated-request.d.ts +27 -0
- package/dist/validated-request.d.ts.map +1 -0
- package/dist/validated-request.js +119 -0
- package/dist/validated-request.js.map +1 -0
- package/package.json +188 -41
- package/dist/lib/client/internal/node/http2-fetch.node.d.ts +0 -2
- package/dist/lib/client/internal/node/http2-fetch.node.d.ts.map +0 -1
- package/dist/lib/client/internal/node/http2-fetch.node.js +0 -131
- package/dist/lib/client/internal/node/http2-fetch.node.js.map +0 -1
- package/dist/lib/client/node.d.ts +0 -5
- package/dist/lib/client/node.d.ts.map +0 -1
- package/dist/lib/client/node.js +0 -33
- package/dist/lib/client/node.js.map +0 -1
- package/dist/tools/api-request/index.d.ts +0 -5
- package/dist/tools/api-request/index.d.ts.map +0 -1
- package/dist/tools/api-request/index.js +0 -4
- package/dist/tools/api-request/index.js.map +0 -1
- package/src/factory.ts +0 -114
- package/src/index.ts +0 -15
- package/src/lib/client/core.ts +0 -13
- package/src/lib/client/internal/base-client.ts +0 -107
- package/src/lib/client/internal/base-helpers.ts +0 -74
- package/src/lib/client/internal/base-types.ts +0 -42
- package/src/lib/client/internal/endpoint.ts +0 -51
- package/src/lib/client/internal/generator.ts +0 -181
- package/src/lib/client/internal/index.ts +0 -4
- package/src/lib/client/internal/node/http2-fetch.node.ts +0 -138
- package/src/lib/client/internal/request-builder.ts +0 -147
- package/src/lib/client/internal/sse-stream.ts +0 -130
- package/src/lib/client/internal/vibes-client.ts +0 -167
- package/src/lib/client/internal/wrap-fetch.ts +0 -59
- package/src/lib/client/node.ts +0 -36
- package/src/lib/client/types.ts +0 -156
- package/src/plugin.ts +0 -104
- package/src/schemas.ts +0 -91
- package/src/sse-client.ts +0 -155
- package/src/tools/api-request/api-request.descriptor.ts +0 -28
- package/src/tools/api-request/api-request.impl.consumer.ts +0 -66
- package/src/tools/api-request/index.ts +0 -4
- package/src/tools/api-request/schemas/index.ts +0 -29
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { getRuntimeEnv } from '@vibesdotdev/runtime';
|
|
2
|
-
import { connect as http2Connect, type ClientHttp2Session } from 'node:http2';
|
|
3
|
-
|
|
4
|
-
export function createHttp2Fetch(
|
|
5
|
-
baseUrl: string
|
|
6
|
-
): (input: Parameters<typeof fetch>[0], init?: RequestInit) => Promise<Response> {
|
|
7
|
-
const sessions = new Map<string, ClientHttp2Session>();
|
|
8
|
-
const rejectUnauthorized = getRuntimeEnv('REJECT_UNAUTHORIZED') !== 'false';
|
|
9
|
-
|
|
10
|
-
return (input: Parameters<typeof fetch>[0], init?: RequestInit): Promise<Response> => {
|
|
11
|
-
const url =
|
|
12
|
-
typeof input === 'string'
|
|
13
|
-
? new URL(input, baseUrl)
|
|
14
|
-
: input instanceof URL
|
|
15
|
-
? input
|
|
16
|
-
: new URL(input.url, baseUrl);
|
|
17
|
-
|
|
18
|
-
const method = init?.method?.toUpperCase() || 'GET';
|
|
19
|
-
const headers = new Headers(init?.headers);
|
|
20
|
-
const sessionKey = `${url.protocol}//${url.host}`;
|
|
21
|
-
let session = sessions.get(sessionKey);
|
|
22
|
-
|
|
23
|
-
if (!session || session.destroyed || session.closed) {
|
|
24
|
-
try {
|
|
25
|
-
session = http2Connect(url.origin, { rejectUnauthorized });
|
|
26
|
-
sessions.set(sessionKey, session);
|
|
27
|
-
session.on('close', () => sessions.delete(sessionKey));
|
|
28
|
-
session.on('error', (error) => {
|
|
29
|
-
if (sessions.has(sessionKey)) {
|
|
30
|
-
console.warn('[http2] Session error:', error.message);
|
|
31
|
-
}
|
|
32
|
-
sessions.delete(sessionKey);
|
|
33
|
-
});
|
|
34
|
-
} catch {
|
|
35
|
-
return fetch(url.toString(), init);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return new Promise((resolve, reject) => {
|
|
40
|
-
try {
|
|
41
|
-
const http2Headers: Record<string, string> = {
|
|
42
|
-
':method': method,
|
|
43
|
-
':path': `${url.pathname}${url.search}`,
|
|
44
|
-
':scheme': url.protocol.replace(':', ''),
|
|
45
|
-
':authority': url.host
|
|
46
|
-
};
|
|
47
|
-
headers.forEach((value, key) => {
|
|
48
|
-
http2Headers[key.toLowerCase()] = value;
|
|
49
|
-
});
|
|
50
|
-
const req = session!.request(http2Headers);
|
|
51
|
-
let settled = false;
|
|
52
|
-
|
|
53
|
-
const abort = () => {
|
|
54
|
-
if (settled) return;
|
|
55
|
-
settled = true;
|
|
56
|
-
try {
|
|
57
|
-
req.close();
|
|
58
|
-
req.destroy();
|
|
59
|
-
} catch {
|
|
60
|
-
// ignore
|
|
61
|
-
}
|
|
62
|
-
const error = new Error('Request aborted');
|
|
63
|
-
error.name = 'AbortError';
|
|
64
|
-
reject(error);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const signal = init?.signal;
|
|
68
|
-
if (signal) {
|
|
69
|
-
if (signal.aborted) {
|
|
70
|
-
abort();
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
signal.addEventListener('abort', abort, { once: true });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const cleanupAbort = () => {
|
|
77
|
-
if (!signal) return;
|
|
78
|
-
signal.removeEventListener('abort', abort);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
if (init?.body) {
|
|
82
|
-
if (typeof init.body === 'string') {
|
|
83
|
-
req.write(init.body);
|
|
84
|
-
} else if (init.body instanceof Buffer) {
|
|
85
|
-
req.write(init.body);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
req.end();
|
|
89
|
-
|
|
90
|
-
const chunks: Buffer[] = [];
|
|
91
|
-
const responseHeaders = new Headers();
|
|
92
|
-
let statusCode = 200;
|
|
93
|
-
|
|
94
|
-
req.on('response', (headers) => {
|
|
95
|
-
const statusValue = headers[':status'];
|
|
96
|
-
statusCode =
|
|
97
|
-
parseInt(Array.isArray(statusValue) ? statusValue[0] : String(statusValue ?? 200)) ||
|
|
98
|
-
200;
|
|
99
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
100
|
-
if (key.startsWith(':') || value === undefined) continue;
|
|
101
|
-
if (Array.isArray(value)) value.forEach((v) => responseHeaders.append(key, v));
|
|
102
|
-
else responseHeaders.set(key, String(value));
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
req.on('data', (chunk) => {
|
|
107
|
-
if (typeof chunk === 'string') {
|
|
108
|
-
chunks.push(Buffer.from(chunk));
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(new Uint8Array(chunk)));
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
req.on('end', () => {
|
|
115
|
-
if (settled) return;
|
|
116
|
-
settled = true;
|
|
117
|
-
cleanupAbort();
|
|
118
|
-
const body = Buffer.concat(chunks);
|
|
119
|
-
resolve(
|
|
120
|
-
new Response(body, {
|
|
121
|
-
status: statusCode,
|
|
122
|
-
headers: responseHeaders
|
|
123
|
-
})
|
|
124
|
-
);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
req.on('error', (error) => {
|
|
128
|
-
if (settled) return;
|
|
129
|
-
settled = true;
|
|
130
|
-
cleanupAbort();
|
|
131
|
-
reject(error);
|
|
132
|
-
});
|
|
133
|
-
} catch (error) {
|
|
134
|
-
reject(error);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
};
|
|
138
|
-
}
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { ClientError, type AuthConfig, type RequestOptions } from '../types.ts';
|
|
2
|
-
|
|
3
|
-
export class RequestBuilder {
|
|
4
|
-
constructor(
|
|
5
|
-
private baseUrl: string,
|
|
6
|
-
private auth: AuthConfig,
|
|
7
|
-
private fetchImpl: typeof fetch,
|
|
8
|
-
private timeout: number = 30000,
|
|
9
|
-
private debug: boolean = false
|
|
10
|
-
) {}
|
|
11
|
-
|
|
12
|
-
async request<T = unknown>(options: RequestOptions): Promise<T> {
|
|
13
|
-
const url = this.buildUrl(options);
|
|
14
|
-
const headers = await this.buildHeaders(options);
|
|
15
|
-
const init: RequestInit = {
|
|
16
|
-
method: options.method,
|
|
17
|
-
headers,
|
|
18
|
-
signal: this.createAbortSignal(options.timeout || this.timeout)
|
|
19
|
-
};
|
|
20
|
-
if (options.body !== undefined) {
|
|
21
|
-
if (headers.get('Content-Type')?.includes('application/json'))
|
|
22
|
-
init.body = JSON.stringify(options.body);
|
|
23
|
-
else init.body = options.body as NonNullable<RequestInit['body']>;
|
|
24
|
-
}
|
|
25
|
-
const shouldLog = this.debug || url.pathname.includes('/auth/');
|
|
26
|
-
if (shouldLog) {
|
|
27
|
-
console.info('[Client] Request:', {
|
|
28
|
-
url: url.toString(),
|
|
29
|
-
method: options.method,
|
|
30
|
-
headers: Object.fromEntries(headers.entries()),
|
|
31
|
-
body: options.body
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
const response = await this.fetchImpl(url.toString(), init);
|
|
36
|
-
if (shouldLog) {
|
|
37
|
-
console.info('[Client] Response:', {
|
|
38
|
-
status: response.status,
|
|
39
|
-
statusText: response.statusText,
|
|
40
|
-
headers: Object.fromEntries(response.headers.entries())
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
if (!response.ok) throw await this.createError(response, options);
|
|
44
|
-
if (response.status === 204 || response.headers.get('Content-Length') === '0')
|
|
45
|
-
return undefined as T;
|
|
46
|
-
const contentType = response.headers.get('Content-Type');
|
|
47
|
-
if (contentType?.includes('application/json')) return (await response.json()) as T;
|
|
48
|
-
return (await response.text()) as T;
|
|
49
|
-
} catch (error) {
|
|
50
|
-
if (this.debug) {
|
|
51
|
-
console.error('[Client] Request failed:', {
|
|
52
|
-
url: url.toString(),
|
|
53
|
-
method: options.method,
|
|
54
|
-
error: error instanceof Error ? error.message : String(error),
|
|
55
|
-
errorName: error instanceof Error ? error.name : undefined
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
if (error instanceof Error && error.name === 'AbortError') {
|
|
59
|
-
throw new ClientError('Request timeout', 408, undefined, options);
|
|
60
|
-
}
|
|
61
|
-
throw error;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private buildUrl(options: RequestOptions): URL {
|
|
66
|
-
let path = options.path;
|
|
67
|
-
if (options.params) {
|
|
68
|
-
for (const [key, value] of Object.entries(options.params)) {
|
|
69
|
-
path = path.replace(`{${key}}`, encodeURIComponent(String(value)));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const url = new URL(path, this.baseUrl);
|
|
73
|
-
if (options.query) {
|
|
74
|
-
for (const [key, value] of Object.entries(options.query)) {
|
|
75
|
-
if (value === undefined) continue;
|
|
76
|
-
if (Array.isArray(value)) value.forEach((v) => url.searchParams.append(key, String(v)));
|
|
77
|
-
else url.searchParams.set(key, String(value));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return url;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private async buildHeaders(options: RequestOptions): Promise<Headers> {
|
|
84
|
-
const headers = new Headers(options.headers);
|
|
85
|
-
if (!headers.has('Content-Type') && options.body !== undefined)
|
|
86
|
-
headers.set('Content-Type', 'application/json');
|
|
87
|
-
if (!headers.has('Accept')) headers.set('Accept', 'application/json');
|
|
88
|
-
if (this.auth.type !== 'none') {
|
|
89
|
-
const token = this.auth.credentials || (await this.auth.tokenProvider?.());
|
|
90
|
-
if (token) {
|
|
91
|
-
switch (this.auth.type) {
|
|
92
|
-
case 'apiKey':
|
|
93
|
-
case 'bearer':
|
|
94
|
-
headers.set('Authorization', `Bearer ${token}`);
|
|
95
|
-
break;
|
|
96
|
-
case 'session':
|
|
97
|
-
headers.set('Cookie', `session=${token}`);
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return headers;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
private createAbortSignal(timeout: number): AbortSignal {
|
|
106
|
-
const controller = new AbortController();
|
|
107
|
-
setTimeout(() => controller.abort(), timeout);
|
|
108
|
-
return controller.signal;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private async createError(response: Response, request: RequestOptions): Promise<ClientError> {
|
|
112
|
-
let message = `${response.status} ${response.statusText}`;
|
|
113
|
-
try {
|
|
114
|
-
const contentType = response.headers.get('Content-Type');
|
|
115
|
-
if (contentType?.includes('application/json')) {
|
|
116
|
-
const error = await response.json();
|
|
117
|
-
const validationErrors =
|
|
118
|
-
(error as { issues?: unknown; errors?: unknown }).issues ??
|
|
119
|
-
(error as { errors?: unknown }).errors;
|
|
120
|
-
if (Array.isArray(validationErrors) && validationErrors.length > 0) {
|
|
121
|
-
const fieldErrors = validationErrors
|
|
122
|
-
.map((issue) => {
|
|
123
|
-
const rec = issue as { path?: unknown; message?: unknown };
|
|
124
|
-
const path =
|
|
125
|
-
Array.isArray(rec.path) && rec.path.length > 0
|
|
126
|
-
? rec.path.map(String).join('.')
|
|
127
|
-
: 'unknown';
|
|
128
|
-
return ` - ${path}: ${typeof rec.message === 'string' ? rec.message : 'Invalid'}`;
|
|
129
|
-
})
|
|
130
|
-
.join('\n');
|
|
131
|
-
message = `Validation failed:\n${fieldErrors}`;
|
|
132
|
-
} else if (typeof (error as { message?: unknown }).message === 'string') {
|
|
133
|
-
message = (error as { message: string }).message;
|
|
134
|
-
} else if ((error as { error?: unknown }).error !== undefined) {
|
|
135
|
-
const e = (error as { error: unknown }).error;
|
|
136
|
-
message = typeof e === 'string' ? e : JSON.stringify(e);
|
|
137
|
-
}
|
|
138
|
-
} else {
|
|
139
|
-
const text = await response.text();
|
|
140
|
-
if (text) message = text;
|
|
141
|
-
}
|
|
142
|
-
} catch {
|
|
143
|
-
// ignore parsing errors
|
|
144
|
-
}
|
|
145
|
-
return new ClientError(message, response.status, response, request);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { type AuthConfig, type RequestOptions, ClientError } from '../types.ts';
|
|
2
|
-
|
|
3
|
-
export interface SSEEvent<T = unknown> {
|
|
4
|
-
event?: string;
|
|
5
|
-
data: T;
|
|
6
|
-
id?: string;
|
|
7
|
-
retry?: number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export type SSEStreamOptions = {
|
|
11
|
-
method?: string;
|
|
12
|
-
params?: Record<string, string | number | boolean>;
|
|
13
|
-
query?: Record<string, string | number | boolean | string[] | undefined>;
|
|
14
|
-
body?: unknown;
|
|
15
|
-
headers?: Record<string, string>;
|
|
16
|
-
timeout?: number;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export async function* streamSSE<T = unknown>(args: {
|
|
20
|
-
baseUrl: string;
|
|
21
|
-
auth: AuthConfig;
|
|
22
|
-
fetchImpl: typeof fetch;
|
|
23
|
-
path: string;
|
|
24
|
-
options?: SSEStreamOptions;
|
|
25
|
-
}): AsyncIterableIterator<SSEEvent<T>> {
|
|
26
|
-
const options = args.options ?? {};
|
|
27
|
-
let url = `${args.baseUrl}${args.path}`;
|
|
28
|
-
if (options.params) {
|
|
29
|
-
for (const [key, value] of Object.entries(options.params)) {
|
|
30
|
-
url = url.replace(`:${key}`, String(value));
|
|
31
|
-
url = url.replace(`{${key}}`, String(value));
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if (options.query) {
|
|
35
|
-
const searchParams = new URLSearchParams();
|
|
36
|
-
for (const [key, value] of Object.entries(options.query)) {
|
|
37
|
-
if (value === undefined || value === null) continue;
|
|
38
|
-
if (Array.isArray(value)) value.forEach((v) => searchParams.append(key, String(v)));
|
|
39
|
-
else searchParams.append(key, String(value));
|
|
40
|
-
}
|
|
41
|
-
const queryString = searchParams.toString();
|
|
42
|
-
if (queryString) url += `?${queryString}`;
|
|
43
|
-
}
|
|
44
|
-
const headers: Record<string, string> = { Accept: 'text/event-stream', ...options.headers };
|
|
45
|
-
if (!('Content-Type' in headers)) headers['Content-Type'] = 'application/json';
|
|
46
|
-
if (args.auth.type === 'apiKey' && args.auth.credentials) {
|
|
47
|
-
headers['X-API-Key'] = args.auth.credentials;
|
|
48
|
-
} else if (args.auth.type === 'bearer') {
|
|
49
|
-
const token = args.auth.tokenProvider ? await args.auth.tokenProvider() : args.auth.credentials;
|
|
50
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
51
|
-
}
|
|
52
|
-
const requestOptions: RequestOptions = {
|
|
53
|
-
method: options.method || 'POST',
|
|
54
|
-
path: args.path,
|
|
55
|
-
params: options.params,
|
|
56
|
-
query: options.query,
|
|
57
|
-
body: options.body,
|
|
58
|
-
headers: options.headers,
|
|
59
|
-
timeout: options.timeout
|
|
60
|
-
};
|
|
61
|
-
const requestInit: RequestInit = { method: requestOptions.method, headers };
|
|
62
|
-
if (requestOptions.timeout) {
|
|
63
|
-
const controller = new AbortController();
|
|
64
|
-
setTimeout(() => controller.abort(), requestOptions.timeout);
|
|
65
|
-
requestInit.signal = controller.signal;
|
|
66
|
-
}
|
|
67
|
-
if (options.body !== undefined) requestInit.body = JSON.stringify(options.body);
|
|
68
|
-
const response = await args.fetchImpl(url, requestInit);
|
|
69
|
-
if (!response.ok) {
|
|
70
|
-
throw new ClientError(
|
|
71
|
-
`SSE stream failed: ${response.statusText}`,
|
|
72
|
-
response.status,
|
|
73
|
-
response,
|
|
74
|
-
requestOptions
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
if (!response.body) {
|
|
78
|
-
throw new ClientError(
|
|
79
|
-
'No response body for SSE stream',
|
|
80
|
-
response.status,
|
|
81
|
-
response,
|
|
82
|
-
requestOptions
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
const reader = response.body.getReader();
|
|
86
|
-
const decoder = new TextDecoder();
|
|
87
|
-
let buffer = '';
|
|
88
|
-
try {
|
|
89
|
-
while (true) {
|
|
90
|
-
const { done, value } = await reader.read();
|
|
91
|
-
if (done) break;
|
|
92
|
-
buffer += decoder.decode(value, { stream: true });
|
|
93
|
-
const lines = buffer.split('\n');
|
|
94
|
-
buffer = lines.pop() || '';
|
|
95
|
-
let currentEvent: Partial<SSEEvent<T>> = {};
|
|
96
|
-
for (const line of lines) {
|
|
97
|
-
if (line.trim() === '') {
|
|
98
|
-
if (currentEvent.data !== undefined) {
|
|
99
|
-
yield currentEvent as SSEEvent<T>;
|
|
100
|
-
currentEvent = {};
|
|
101
|
-
}
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
if (line.startsWith('event:')) {
|
|
105
|
-
currentEvent.event = line.slice(6).trim();
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
if (line.startsWith('data:')) {
|
|
109
|
-
const dataStr = line.slice(5).trim();
|
|
110
|
-
if (dataStr === '[DONE]') return;
|
|
111
|
-
try {
|
|
112
|
-
currentEvent.data = JSON.parse(dataStr) as T;
|
|
113
|
-
} catch {
|
|
114
|
-
currentEvent.data = dataStr as T;
|
|
115
|
-
}
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
if (line.startsWith('id:')) {
|
|
119
|
-
currentEvent.id = line.slice(3).trim();
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
if (line.startsWith('retry:')) {
|
|
123
|
-
currentEvent.retry = parseInt(line.slice(6).trim());
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
} finally {
|
|
128
|
-
reader.releaseLock();
|
|
129
|
-
}
|
|
130
|
-
}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import type { AuthConfig, ClientConfig, ClientHooks, RequestOptions } from '../types.ts';
|
|
2
|
-
import { APIGenerator, type OpenAPISpec } from './generator.ts';
|
|
3
|
-
import { getRuntimeEnv } from '@vibesdotdev/runtime';
|
|
4
|
-
import { RequestBuilder } from './request-builder.ts';
|
|
5
|
-
import { streamSSE, type SSEEvent, type SSEStreamOptions } from './sse-stream.ts';
|
|
6
|
-
import { createHookedFetch } from './wrap-fetch.ts';
|
|
7
|
-
|
|
8
|
-
interface ResolvedClientConfig {
|
|
9
|
-
baseUrl: string;
|
|
10
|
-
auth: AuthConfig;
|
|
11
|
-
fetch: typeof fetch;
|
|
12
|
-
hooks: ClientHooks;
|
|
13
|
-
timeout: number;
|
|
14
|
-
debug: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class VibesClient {
|
|
18
|
-
private config: ResolvedClientConfig;
|
|
19
|
-
private requestBuilder: RequestBuilder;
|
|
20
|
-
private apiGenerator: APIGenerator;
|
|
21
|
-
private apis: Record<string, unknown> = {};
|
|
22
|
-
private specPromise: Promise<OpenAPISpec> | null = null;
|
|
23
|
-
|
|
24
|
-
constructor(config: ClientConfig = {}) {
|
|
25
|
-
const baseUrl =
|
|
26
|
-
config.baseUrl ||
|
|
27
|
-
getRuntimeEnv('VIBES_API_URL') ||
|
|
28
|
-
'http://localhost:5173';
|
|
29
|
-
const fetchImpl = config.fetch || globalThis.fetch?.bind(globalThis);
|
|
30
|
-
if (!fetchImpl)
|
|
31
|
-
throw new Error('Fetch is not available. Please provide a fetch implementation.');
|
|
32
|
-
const hooks = config.hooks || {};
|
|
33
|
-
this.config = {
|
|
34
|
-
baseUrl,
|
|
35
|
-
auth: config.auth || { type: 'none' },
|
|
36
|
-
fetch: fetchImpl as typeof fetch,
|
|
37
|
-
hooks,
|
|
38
|
-
timeout: config.timeout || 30000,
|
|
39
|
-
debug: config.debug || false
|
|
40
|
-
};
|
|
41
|
-
const hookedFetch = createHookedFetch({
|
|
42
|
-
fetchImpl: this.config.fetch,
|
|
43
|
-
hooks: this.config.hooks
|
|
44
|
-
});
|
|
45
|
-
this.requestBuilder = new RequestBuilder(
|
|
46
|
-
this.config.baseUrl,
|
|
47
|
-
this.config.auth,
|
|
48
|
-
hookedFetch as typeof fetch,
|
|
49
|
-
this.config.timeout,
|
|
50
|
-
this.config.debug
|
|
51
|
-
);
|
|
52
|
-
this.apiGenerator = new APIGenerator(this.requestBuilder);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private async initialize(): Promise<void> {
|
|
56
|
-
try {
|
|
57
|
-
const spec = await this.getOpenAPISpec();
|
|
58
|
-
this.buildAPIs(spec);
|
|
59
|
-
} catch (error) {
|
|
60
|
-
const shouldWarn =
|
|
61
|
-
this.config.debug ||
|
|
62
|
-
(typeof process !== 'undefined' && process.env?.VIBES_CLIENT_WARN_OAS === 'true');
|
|
63
|
-
if (shouldWarn) {
|
|
64
|
-
console.warn('Failed to load OpenAPI spec, client will have limited functionality:', error);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
getOpenAPISpec(): Promise<OpenAPISpec> {
|
|
70
|
-
if (!this.specPromise) this.specPromise = this.fetchOpenAPISpec();
|
|
71
|
-
return this.specPromise;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
private async fetchOpenAPISpec(): Promise<OpenAPISpec> {
|
|
75
|
-
const response = await this.config.fetch(`${this.config.baseUrl}/api/docs/openapi.json`);
|
|
76
|
-
if (!response.ok) throw new Error(`Failed to fetch OpenAPI spec: ${response.statusText}`);
|
|
77
|
-
return response.json() as Promise<OpenAPISpec>;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private buildAPIs(spec: OpenAPISpec): void {
|
|
81
|
-
const apis = this.apiGenerator.generateAPIs(spec);
|
|
82
|
-
for (const [name, api] of Object.entries(apis)) {
|
|
83
|
-
this.apis[name] = api;
|
|
84
|
-
Object.defineProperty(this, name, {
|
|
85
|
-
get: () => this.apis[name],
|
|
86
|
-
enumerable: true,
|
|
87
|
-
configurable: true
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
request<T = unknown>(
|
|
93
|
-
path: string,
|
|
94
|
-
options: {
|
|
95
|
-
method?: string;
|
|
96
|
-
params?: Record<string, string | number | boolean>;
|
|
97
|
-
query?: Record<string, string | number | boolean | string[] | undefined>;
|
|
98
|
-
body?: unknown;
|
|
99
|
-
headers?: Record<string, string>;
|
|
100
|
-
timeout?: number;
|
|
101
|
-
} = {}
|
|
102
|
-
): Promise<T> {
|
|
103
|
-
return this.requestBuilder.request({
|
|
104
|
-
path,
|
|
105
|
-
method: options.method || 'GET',
|
|
106
|
-
params: options.params,
|
|
107
|
-
query: options.query,
|
|
108
|
-
body: options.body,
|
|
109
|
-
headers: options.headers,
|
|
110
|
-
timeout: options.timeout
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
setAuth(auth: AuthConfig): void {
|
|
115
|
-
this.config.auth = auth;
|
|
116
|
-
const hookedFetch = createHookedFetch({
|
|
117
|
-
fetchImpl: this.config.fetch,
|
|
118
|
-
hooks: this.config.hooks
|
|
119
|
-
});
|
|
120
|
-
this.requestBuilder = new RequestBuilder(
|
|
121
|
-
this.config.baseUrl,
|
|
122
|
-
auth,
|
|
123
|
-
hookedFetch as typeof fetch,
|
|
124
|
-
this.config.timeout,
|
|
125
|
-
this.config.debug
|
|
126
|
-
);
|
|
127
|
-
this.apiGenerator = new APIGenerator(this.requestBuilder);
|
|
128
|
-
if (this.specPromise) this.specPromise.then((spec) => this.buildAPIs(spec));
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
getResources(): string[] {
|
|
132
|
-
return Object.keys(this.apis);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
hasResource(name: string): boolean {
|
|
136
|
-
return name in this.apis;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
get<T = unknown>(endpoint: string, options?: RequestOptions): Promise<T> {
|
|
140
|
-
return this.request<T>(endpoint, { ...options, method: 'GET' });
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
post<T = unknown>(endpoint: string, body?: unknown, options?: RequestOptions): Promise<T> {
|
|
144
|
-
return this.request<T>(endpoint, { ...options, method: 'POST', body });
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
put<T = unknown>(endpoint: string, body?: unknown, options?: RequestOptions): Promise<T> {
|
|
148
|
-
return this.request<T>(endpoint, { ...options, method: 'PUT', body });
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
delete<T = unknown>(endpoint: string, options?: RequestOptions): Promise<T> {
|
|
152
|
-
return this.request<T>(endpoint, { ...options, method: 'DELETE' });
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async *stream<T = unknown>(
|
|
156
|
-
path: string,
|
|
157
|
-
options: SSEStreamOptions = {}
|
|
158
|
-
): AsyncIterableIterator<SSEEvent<T>> {
|
|
159
|
-
yield* streamSSE<T>({
|
|
160
|
-
baseUrl: this.config.baseUrl,
|
|
161
|
-
auth: this.config.auth,
|
|
162
|
-
fetchImpl: this.config.fetch,
|
|
163
|
-
path,
|
|
164
|
-
options
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { ClientError, type ClientHooks } from '../types.ts';
|
|
2
|
-
|
|
3
|
-
export function createHookedFetch(args: {
|
|
4
|
-
fetchImpl: typeof fetch;
|
|
5
|
-
hooks: ClientHooks;
|
|
6
|
-
}): (input: Parameters<typeof fetch>[0], init?: RequestInit) => Promise<Response> {
|
|
7
|
-
return async (input: Parameters<typeof fetch>[0], init?: RequestInit) => {
|
|
8
|
-
if (!args.hooks.beforeRequest) {
|
|
9
|
-
let response: Response;
|
|
10
|
-
try {
|
|
11
|
-
response = await args.fetchImpl(input, init);
|
|
12
|
-
} catch (error) {
|
|
13
|
-
if (args.hooks.onError) {
|
|
14
|
-
await args.hooks.onError(
|
|
15
|
-
new ClientError(
|
|
16
|
-
error instanceof Error ? error.message : 'Network error',
|
|
17
|
-
0,
|
|
18
|
-
undefined,
|
|
19
|
-
undefined
|
|
20
|
-
)
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
throw error;
|
|
24
|
-
}
|
|
25
|
-
if (args.hooks.afterResponse) response = await args.hooks.afterResponse(response);
|
|
26
|
-
return response;
|
|
27
|
-
}
|
|
28
|
-
const requestInput = input instanceof URL
|
|
29
|
-
? new Request(input.href, init)
|
|
30
|
-
: typeof input === 'string'
|
|
31
|
-
? new Request(input, init)
|
|
32
|
-
: new Request(input, init);
|
|
33
|
-
const modifiedRequest = await args.hooks.beforeRequest(requestInput);
|
|
34
|
-
const modifiedInit: RequestInit = {
|
|
35
|
-
...init,
|
|
36
|
-
method: modifiedRequest.method,
|
|
37
|
-
headers: Object.fromEntries(modifiedRequest.headers.entries()),
|
|
38
|
-
...(modifiedRequest.body !== requestInput.body && { body: modifiedRequest.body })
|
|
39
|
-
};
|
|
40
|
-
let response: Response;
|
|
41
|
-
try {
|
|
42
|
-
response = await args.fetchImpl(modifiedRequest.url, modifiedInit);
|
|
43
|
-
} catch (error) {
|
|
44
|
-
if (args.hooks.onError) {
|
|
45
|
-
await args.hooks.onError(
|
|
46
|
-
new ClientError(
|
|
47
|
-
error instanceof Error ? error.message : 'Network error',
|
|
48
|
-
0,
|
|
49
|
-
undefined,
|
|
50
|
-
undefined
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
throw error;
|
|
55
|
-
}
|
|
56
|
-
if (args.hooks.afterResponse) response = await args.hooks.afterResponse(response);
|
|
57
|
-
return response;
|
|
58
|
-
};
|
|
59
|
-
}
|
package/src/lib/client/node.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { getRuntimeEnv } from '@vibesdotdev/runtime';
|
|
2
|
-
import type { ClientConfig } from './types.ts';
|
|
3
|
-
import { VibesClient } from './internal/vibes-client.ts';
|
|
4
|
-
|
|
5
|
-
export { createHttp2Fetch } from './internal/node/http2-fetch.node.ts';
|
|
6
|
-
|
|
7
|
-
async function resolveNodeFetch(baseUrl: string): Promise<typeof globalThis.fetch> {
|
|
8
|
-
const isHttps = baseUrl.startsWith('https://');
|
|
9
|
-
const isLocal =
|
|
10
|
-
baseUrl.includes('.local') || baseUrl.includes('localhost') || baseUrl.includes('127.0.0.1');
|
|
11
|
-
if (isHttps && isLocal) {
|
|
12
|
-
try {
|
|
13
|
-
if (!getRuntimeEnv('REJECT_UNAUTHORIZED')) {
|
|
14
|
-
globalThis.process?.['env'] && (globalThis.process.env.REJECT_UNAUTHORIZED = 'false');
|
|
15
|
-
}
|
|
16
|
-
const { createHttp2Fetch } = await import('./internal/node/http2-fetch.node.js');
|
|
17
|
-
return createHttp2Fetch(baseUrl) as unknown as typeof globalThis.fetch;
|
|
18
|
-
} catch {
|
|
19
|
-
// Fallback to regular fetch if h2 module unavailable
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return globalThis.fetch;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export async function createCLIClient(config?: Partial<ClientConfig>): Promise<VibesClient> {
|
|
26
|
-
const baseUrl = config?.baseUrl || getRuntimeEnv('VIBES_API_URL') || 'http://localhost:5173';
|
|
27
|
-
const fetchImpl = config?.fetch || (await resolveNodeFetch(baseUrl));
|
|
28
|
-
const clientConfig: ClientConfig = {
|
|
29
|
-
baseUrl,
|
|
30
|
-
auth: config?.auth || { type: 'none' },
|
|
31
|
-
fetch: fetchImpl,
|
|
32
|
-
debug: getRuntimeEnv('VIBES_DEBUG') === 'true',
|
|
33
|
-
...config
|
|
34
|
-
};
|
|
35
|
-
return new VibesClient(clientConfig);
|
|
36
|
-
}
|