@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.
Files changed (238) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +24 -15
  3. package/dist/api-client-plugin.d.ts +4 -0
  4. package/dist/api-client-plugin.d.ts.map +1 -0
  5. package/dist/api-client-plugin.js +20 -0
  6. package/dist/api-client-plugin.js.map +1 -0
  7. package/dist/api-client.impl.d.ts +23 -0
  8. package/dist/api-client.impl.d.ts.map +1 -0
  9. package/dist/api-client.impl.js +47 -0
  10. package/dist/api-client.impl.js.map +1 -0
  11. package/dist/client.consumer.plugin.d.ts +3 -0
  12. package/dist/client.consumer.plugin.d.ts.map +1 -0
  13. package/dist/client.consumer.plugin.js +10 -0
  14. package/dist/client.consumer.plugin.js.map +1 -0
  15. package/dist/cloud.plugin.d.ts +3 -0
  16. package/dist/cloud.plugin.d.ts.map +1 -0
  17. package/dist/cloud.plugin.js +10 -0
  18. package/dist/cloud.plugin.js.map +1 -0
  19. package/dist/config/client.config.descriptor.d.ts +4 -0
  20. package/dist/config/client.config.descriptor.d.ts.map +1 -0
  21. package/dist/config/client.config.descriptor.js +32 -0
  22. package/dist/config/client.config.descriptor.js.map +1 -0
  23. package/dist/config/index.d.ts +3 -0
  24. package/dist/config/index.d.ts.map +1 -0
  25. package/dist/config/index.js +3 -0
  26. package/dist/config/index.js.map +1 -0
  27. package/dist/config/settings.d.ts +9 -0
  28. package/dist/config/settings.d.ts.map +1 -0
  29. package/dist/config/settings.js +25 -0
  30. package/dist/config/settings.js.map +1 -0
  31. package/dist/docs/client.api-request.docs.descriptor.d.ts +4 -0
  32. package/dist/docs/client.api-request.docs.descriptor.d.ts.map +1 -0
  33. package/dist/docs/client.api-request.docs.descriptor.js +71 -0
  34. package/dist/docs/client.api-request.docs.descriptor.js.map +1 -0
  35. package/dist/events/auth-rejected.event.d.ts +35 -0
  36. package/dist/events/auth-rejected.event.d.ts.map +1 -0
  37. package/dist/events/auth-rejected.event.js +36 -0
  38. package/dist/events/auth-rejected.event.js.map +1 -0
  39. package/dist/factory.d.ts +5 -1
  40. package/dist/factory.d.ts.map +1 -1
  41. package/dist/factory.js +16 -17
  42. package/dist/factory.js.map +1 -1
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +2 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/kind-augment.d.ts +11 -0
  48. package/dist/kind-augment.d.ts.map +1 -0
  49. package/dist/kind-augment.js +2 -0
  50. package/dist/kind-augment.js.map +1 -0
  51. package/dist/lib/client/api-diagnostics.d.ts +79 -0
  52. package/dist/lib/client/api-diagnostics.d.ts.map +1 -0
  53. package/dist/lib/client/api-diagnostics.js +111 -0
  54. package/dist/lib/client/api-diagnostics.js.map +1 -0
  55. package/dist/lib/client/configured.d.ts +78 -0
  56. package/dist/lib/client/configured.d.ts.map +1 -0
  57. package/dist/lib/client/configured.js +261 -0
  58. package/dist/lib/client/configured.js.map +1 -0
  59. package/dist/lib/client/internal/auth-headers.d.ts +11 -0
  60. package/dist/lib/client/internal/auth-headers.d.ts.map +1 -0
  61. package/dist/lib/client/internal/auth-headers.js +35 -0
  62. package/dist/lib/client/internal/auth-headers.js.map +1 -0
  63. package/dist/lib/client/internal/base-client.d.ts +5 -2
  64. package/dist/lib/client/internal/base-client.d.ts.map +1 -1
  65. package/dist/lib/client/internal/base-client.js +42 -22
  66. package/dist/lib/client/internal/base-client.js.map +1 -1
  67. package/dist/lib/client/internal/base-helpers.d.ts.map +1 -1
  68. package/dist/lib/client/internal/base-helpers.js +20 -20
  69. package/dist/lib/client/internal/base-helpers.js.map +1 -1
  70. package/dist/lib/client/internal/base-types.d.ts +10 -5
  71. package/dist/lib/client/internal/base-types.d.ts.map +1 -1
  72. package/dist/lib/client/internal/base-types.js +5 -3
  73. package/dist/lib/client/internal/base-types.js.map +1 -1
  74. package/dist/lib/client/internal/client-values.d.ts +43 -0
  75. package/dist/lib/client/internal/client-values.d.ts.map +1 -0
  76. package/dist/lib/client/internal/client-values.js +76 -0
  77. package/dist/lib/client/internal/client-values.js.map +1 -0
  78. package/dist/lib/client/internal/endpoint.d.ts +6 -5
  79. package/dist/lib/client/internal/endpoint.d.ts.map +1 -1
  80. package/dist/lib/client/internal/endpoint.js +3 -0
  81. package/dist/lib/client/internal/endpoint.js.map +1 -1
  82. package/dist/lib/client/internal/generator.d.ts +98 -9
  83. package/dist/lib/client/internal/generator.d.ts.map +1 -1
  84. package/dist/lib/client/internal/generator.js +92 -140
  85. package/dist/lib/client/internal/generator.js.map +1 -1
  86. package/dist/lib/client/internal/request-builder.d.ts +5 -2
  87. package/dist/lib/client/internal/request-builder.d.ts.map +1 -1
  88. package/dist/lib/client/internal/request-builder.js +105 -65
  89. package/dist/lib/client/internal/request-builder.js.map +1 -1
  90. package/dist/lib/client/internal/sse-stream.d.ts +9 -5
  91. package/dist/lib/client/internal/sse-stream.d.ts.map +1 -1
  92. package/dist/lib/client/internal/sse-stream.js +96 -94
  93. package/dist/lib/client/internal/sse-stream.js.map +1 -1
  94. package/dist/lib/client/internal/timeout-signal.d.ts +8 -0
  95. package/dist/lib/client/internal/timeout-signal.d.ts.map +1 -0
  96. package/dist/lib/client/internal/timeout-signal.js +17 -0
  97. package/dist/lib/client/internal/timeout-signal.js.map +1 -0
  98. package/dist/lib/client/internal/transport/http2-fetch.d.ts +8 -0
  99. package/dist/lib/client/internal/transport/http2-fetch.d.ts.map +1 -0
  100. package/dist/lib/client/internal/transport/http2-fetch.js +17 -0
  101. package/dist/lib/client/internal/transport/http2-fetch.js.map +1 -0
  102. package/dist/lib/client/internal/vibes-client.d.ts +17 -8
  103. package/dist/lib/client/internal/vibes-client.d.ts.map +1 -1
  104. package/dist/lib/client/internal/vibes-client.js +127 -67
  105. package/dist/lib/client/internal/vibes-client.js.map +1 -1
  106. package/dist/lib/client/internal/wrap-fetch.d.ts +3 -2
  107. package/dist/lib/client/internal/wrap-fetch.d.ts.map +1 -1
  108. package/dist/lib/client/internal/wrap-fetch.js +14 -33
  109. package/dist/lib/client/internal/wrap-fetch.js.map +1 -1
  110. package/dist/lib/client/runtime-fetch.d.ts +14 -0
  111. package/dist/lib/client/runtime-fetch.d.ts.map +1 -0
  112. package/dist/lib/client/runtime-fetch.js +25 -0
  113. package/dist/lib/client/runtime-fetch.js.map +1 -0
  114. package/dist/lib/client/types.d.ts +18 -9
  115. package/dist/lib/client/types.d.ts.map +1 -1
  116. package/dist/lib/client/types.js +22 -3
  117. package/dist/lib/client/types.js.map +1 -1
  118. package/dist/plugin.d.ts +2 -18
  119. package/dist/plugin.d.ts.map +1 -1
  120. package/dist/plugin.js +7 -74
  121. package/dist/plugin.js.map +1 -1
  122. package/dist/runtime-client.d.ts +10 -0
  123. package/dist/runtime-client.d.ts.map +1 -0
  124. package/dist/runtime-client.js +14 -0
  125. package/dist/runtime-client.js.map +1 -0
  126. package/dist/schemas/auth-rejected.d.ts +12 -0
  127. package/dist/schemas/auth-rejected.d.ts.map +1 -0
  128. package/dist/schemas/auth-rejected.js +11 -0
  129. package/dist/schemas/auth-rejected.js.map +1 -0
  130. package/dist/schemas/sdk-languages.d.ts +47 -0
  131. package/dist/schemas/sdk-languages.d.ts.map +1 -0
  132. package/dist/schemas/sdk-languages.js +75 -0
  133. package/dist/schemas/sdk-languages.js.map +1 -0
  134. package/dist/schemas/settings.d.ts +14 -0
  135. package/dist/schemas/settings.d.ts.map +1 -0
  136. package/dist/schemas/settings.js +10 -0
  137. package/dist/schemas/settings.js.map +1 -0
  138. package/dist/schemas/validated-request.d.ts +19 -0
  139. package/dist/schemas/validated-request.d.ts.map +1 -0
  140. package/dist/schemas/validated-request.js +2 -0
  141. package/dist/schemas/validated-request.js.map +1 -0
  142. package/dist/schemas.d.ts +23 -8
  143. package/dist/schemas.d.ts.map +1 -1
  144. package/dist/schemas.js +8 -2
  145. package/dist/schemas.js.map +1 -1
  146. package/dist/sse-client.d.ts +17 -15
  147. package/dist/sse-client.d.ts.map +1 -1
  148. package/dist/sse-client.js +111 -91
  149. package/dist/sse-client.js.map +1 -1
  150. package/dist/svelte/client-svelte.plugin.d.ts +5 -0
  151. package/dist/svelte/client-svelte.plugin.d.ts.map +1 -0
  152. package/dist/svelte/client-svelte.plugin.js +46 -0
  153. package/dist/svelte/index.d.ts +3 -0
  154. package/dist/svelte/index.d.ts.map +1 -0
  155. package/dist/svelte/index.js +2 -0
  156. package/dist/svelte/styles.css +8 -0
  157. package/dist/svelte/tool-widgets/ApiRequestToolCard.svelte +53 -0
  158. package/dist/svelte/tool-widgets/ApiRequestToolCard.svelte.d.ts +5 -0
  159. package/dist/svelte/tool-widgets/ApiRequestToolCard.svelte.d.ts.map +1 -0
  160. package/dist/svelte/tool-widgets/index.d.ts +2 -0
  161. package/dist/svelte/tool-widgets/index.d.ts.map +1 -0
  162. package/dist/svelte/tool-widgets/index.js +1 -0
  163. package/dist/tools/api-request/api-request.contract.d.ts +19 -0
  164. package/dist/tools/api-request/api-request.contract.d.ts.map +1 -0
  165. package/dist/tools/api-request/api-request.contract.js +110 -0
  166. package/dist/tools/api-request/api-request.contract.js.map +1 -0
  167. package/dist/tools/api-request/api-request.descriptor.d.ts +11 -4
  168. package/dist/tools/api-request/api-request.descriptor.d.ts.map +1 -1
  169. package/dist/tools/api-request/api-request.descriptor.js +8 -5
  170. package/dist/tools/api-request/api-request.descriptor.js.map +1 -1
  171. package/dist/tools/api-request/api-request.impl.cloud.d.ts +15 -0
  172. package/dist/tools/api-request/api-request.impl.cloud.d.ts.map +1 -0
  173. package/dist/tools/api-request/api-request.impl.cloud.js +75 -0
  174. package/dist/tools/api-request/api-request.impl.cloud.js.map +1 -0
  175. package/dist/tools/api-request/api-request.impl.consumer.d.ts +5 -3
  176. package/dist/tools/api-request/api-request.impl.consumer.d.ts.map +1 -1
  177. package/dist/tools/api-request/api-request.impl.consumer.js +27 -33
  178. package/dist/tools/api-request/api-request.impl.consumer.js.map +1 -1
  179. package/dist/tools/api-request/api-request.view.d.ts +29 -0
  180. package/dist/tools/api-request/api-request.view.d.ts.map +1 -0
  181. package/dist/tools/api-request/api-request.view.js +62 -0
  182. package/dist/tools/api-request/api-request.view.js.map +1 -0
  183. package/dist/tools/api-request/schemas/index.d.ts +12 -5
  184. package/dist/tools/api-request/schemas/index.d.ts.map +1 -1
  185. package/dist/tools/api-request/schemas/index.js +24 -6
  186. package/dist/tools/api-request/schemas/index.js.map +1 -1
  187. package/dist/tui/client-tui.plugin.d.ts +3 -0
  188. package/dist/tui/client-tui.plugin.d.ts.map +1 -0
  189. package/dist/tui/client-tui.plugin.js +32 -0
  190. package/dist/tui/client-tui.plugin.js.map +1 -0
  191. package/dist/tui/index.d.ts +2 -0
  192. package/dist/tui/index.d.ts.map +1 -0
  193. package/dist/tui/index.js +2 -0
  194. package/dist/tui/index.js.map +1 -0
  195. package/dist/tui/tool-widgets/ApiRequestToolWidget.impl.tui.d.ts +17 -0
  196. package/dist/tui/tool-widgets/ApiRequestToolWidget.impl.tui.d.ts.map +1 -0
  197. package/dist/tui/tool-widgets/ApiRequestToolWidget.impl.tui.js +28 -0
  198. package/dist/tui/tool-widgets/ApiRequestToolWidget.impl.tui.js.map +1 -0
  199. package/dist/validated-request.d.ts +27 -0
  200. package/dist/validated-request.d.ts.map +1 -0
  201. package/dist/validated-request.js +119 -0
  202. package/dist/validated-request.js.map +1 -0
  203. package/package.json +188 -41
  204. package/dist/lib/client/internal/node/http2-fetch.node.d.ts +0 -2
  205. package/dist/lib/client/internal/node/http2-fetch.node.d.ts.map +0 -1
  206. package/dist/lib/client/internal/node/http2-fetch.node.js +0 -131
  207. package/dist/lib/client/internal/node/http2-fetch.node.js.map +0 -1
  208. package/dist/lib/client/node.d.ts +0 -5
  209. package/dist/lib/client/node.d.ts.map +0 -1
  210. package/dist/lib/client/node.js +0 -33
  211. package/dist/lib/client/node.js.map +0 -1
  212. package/dist/tools/api-request/index.d.ts +0 -5
  213. package/dist/tools/api-request/index.d.ts.map +0 -1
  214. package/dist/tools/api-request/index.js +0 -4
  215. package/dist/tools/api-request/index.js.map +0 -1
  216. package/src/factory.ts +0 -114
  217. package/src/index.ts +0 -15
  218. package/src/lib/client/core.ts +0 -13
  219. package/src/lib/client/internal/base-client.ts +0 -107
  220. package/src/lib/client/internal/base-helpers.ts +0 -74
  221. package/src/lib/client/internal/base-types.ts +0 -42
  222. package/src/lib/client/internal/endpoint.ts +0 -51
  223. package/src/lib/client/internal/generator.ts +0 -181
  224. package/src/lib/client/internal/index.ts +0 -4
  225. package/src/lib/client/internal/node/http2-fetch.node.ts +0 -138
  226. package/src/lib/client/internal/request-builder.ts +0 -147
  227. package/src/lib/client/internal/sse-stream.ts +0 -130
  228. package/src/lib/client/internal/vibes-client.ts +0 -167
  229. package/src/lib/client/internal/wrap-fetch.ts +0 -59
  230. package/src/lib/client/node.ts +0 -36
  231. package/src/lib/client/types.ts +0 -156
  232. package/src/plugin.ts +0 -104
  233. package/src/schemas.ts +0 -91
  234. package/src/sse-client.ts +0 -155
  235. package/src/tools/api-request/api-request.descriptor.ts +0 -28
  236. package/src/tools/api-request/api-request.impl.consumer.ts +0 -66
  237. package/src/tools/api-request/index.ts +0 -4
  238. 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
- }
@@ -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
- }