@tanstack/ai-worldlabs 0.0.0 → 0.1.0

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 (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -2
  3. package/dist/esm/adapters/world.d.ts +38 -0
  4. package/dist/esm/adapters/world.js +314 -0
  5. package/dist/esm/adapters/world.js.map +1 -0
  6. package/dist/esm/byok.d.ts +1 -0
  7. package/dist/esm/byok.js +11 -0
  8. package/dist/esm/byok.js.map +1 -0
  9. package/dist/esm/generated/client/client.gen.d.ts +2 -0
  10. package/dist/esm/generated/client/client.gen.js +174 -0
  11. package/dist/esm/generated/client/client.gen.js.map +1 -0
  12. package/dist/esm/generated/client/index.d.ts +10 -0
  13. package/dist/esm/generated/client/index.js +5 -0
  14. package/dist/esm/generated/client/types.gen.d.ts +120 -0
  15. package/dist/esm/generated/client/utils.gen.d.ts +37 -0
  16. package/dist/esm/generated/client/utils.gen.js +177 -0
  17. package/dist/esm/generated/client/utils.gen.js.map +1 -0
  18. package/dist/esm/generated/client.d.ts +1 -0
  19. package/dist/esm/generated/client.gen.d.ts +12 -0
  20. package/dist/esm/generated/client.gen.js +9 -0
  21. package/dist/esm/generated/client.gen.js.map +1 -0
  22. package/dist/esm/generated/client.js +5 -0
  23. package/dist/esm/generated/core/auth.gen.d.ts +25 -0
  24. package/dist/esm/generated/core/auth.gen.js +12 -0
  25. package/dist/esm/generated/core/auth.gen.js.map +1 -0
  26. package/dist/esm/generated/core/bodySerializer.gen.d.ts +25 -0
  27. package/dist/esm/generated/core/bodySerializer.gen.js +6 -0
  28. package/dist/esm/generated/core/bodySerializer.gen.js.map +1 -0
  29. package/dist/esm/generated/core/params.gen.d.ts +43 -0
  30. package/dist/esm/generated/core/params.gen.js +9 -0
  31. package/dist/esm/generated/core/params.gen.js.map +1 -0
  32. package/dist/esm/generated/core/pathSerializer.gen.d.ts +33 -0
  33. package/dist/esm/generated/core/pathSerializer.gen.js +82 -0
  34. package/dist/esm/generated/core/pathSerializer.gen.js.map +1 -0
  35. package/dist/esm/generated/core/queryKeySerializer.gen.d.ts +18 -0
  36. package/dist/esm/generated/core/serverSentEvents.gen.d.ts +71 -0
  37. package/dist/esm/generated/core/serverSentEvents.gen.js +96 -0
  38. package/dist/esm/generated/core/serverSentEvents.gen.js.map +1 -0
  39. package/dist/esm/generated/core/types.gen.d.ts +83 -0
  40. package/dist/esm/generated/core/utils.gen.d.ts +19 -0
  41. package/dist/esm/generated/core/utils.gen.js +78 -0
  42. package/dist/esm/generated/core/utils.gen.js.map +1 -0
  43. package/dist/esm/generated/index.d.ts +2 -0
  44. package/dist/esm/generated/sdk.gen.d.ts +275 -0
  45. package/dist/esm/generated/sdk.gen.js +79 -0
  46. package/dist/esm/generated/sdk.gen.js.map +1 -0
  47. package/dist/esm/generated/types.gen.d.ts +1610 -0
  48. package/dist/esm/index.d.ts +5 -0
  49. package/dist/esm/index.js +4 -0
  50. package/dist/esm/model-meta.d.ts +63 -0
  51. package/dist/esm/model-meta.js +17 -0
  52. package/dist/esm/model-meta.js.map +1 -0
  53. package/dist/esm/utils/client.d.ts +16 -0
  54. package/dist/esm/utils/client.js +35 -0
  55. package/dist/esm/utils/client.js.map +1 -0
  56. package/package.json +54 -6
  57. package/src/adapters/world.ts +535 -0
  58. package/src/byok.ts +7 -0
  59. package/src/generated/client/client.gen.ts +301 -0
  60. package/src/generated/client/index.ts +27 -0
  61. package/src/generated/client/types.gen.ts +247 -0
  62. package/src/generated/client/utils.gen.ts +332 -0
  63. package/src/generated/client.gen.ts +26 -0
  64. package/src/generated/client.ts +3 -0
  65. package/src/generated/core/auth.gen.ts +48 -0
  66. package/src/generated/core/bodySerializer.gen.ts +96 -0
  67. package/src/generated/core/params.gen.ts +186 -0
  68. package/src/generated/core/pathSerializer.gen.ts +186 -0
  69. package/src/generated/core/queryKeySerializer.gen.ts +139 -0
  70. package/src/generated/core/serverSentEvents.gen.ts +265 -0
  71. package/src/generated/core/types.gen.ts +124 -0
  72. package/src/generated/core/utils.gen.ts +146 -0
  73. package/src/generated/index.ts +113 -0
  74. package/src/generated/sdk.gen.ts +531 -0
  75. package/src/generated/types.gen.ts +1767 -0
  76. package/src/index.ts +20 -0
  77. package/src/model-meta.ts +79 -0
  78. package/src/utils/client.ts +50 -0
@@ -0,0 +1,301 @@
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 {
7
+ Client,
8
+ Config,
9
+ RequestOptions,
10
+ ResolvedRequestOptions,
11
+ } from './types.gen'
12
+ import {
13
+ buildUrl,
14
+ createConfig,
15
+ createInterceptors,
16
+ getParseAs,
17
+ mergeConfigs,
18
+ mergeHeaders,
19
+ setAuthParams,
20
+ } from './utils.gen'
21
+
22
+ type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
23
+ body?: any
24
+ headers: ReturnType<typeof mergeHeaders>
25
+ }
26
+
27
+ export const createClient = (config: Config = {}): Client => {
28
+ let _config = mergeConfigs(createConfig(), config)
29
+
30
+ const getConfig = (): Config => ({ ..._config })
31
+
32
+ const setConfig = (config: Config): Config => {
33
+ _config = mergeConfigs(_config, config)
34
+ return getConfig()
35
+ }
36
+
37
+ const interceptors = createInterceptors<
38
+ Request,
39
+ Response,
40
+ unknown,
41
+ ResolvedRequestOptions
42
+ >()
43
+
44
+ const beforeRequest = async <
45
+ TData = unknown,
46
+ TResponseStyle extends 'data' | 'fields' = 'fields',
47
+ ThrowOnError extends boolean = boolean,
48
+ Url extends string = string,
49
+ >(
50
+ options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
51
+ ) => {
52
+ const opts = {
53
+ ..._config,
54
+ ...options,
55
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
56
+ headers: mergeHeaders(_config.headers, options.headers),
57
+ serializedBody: undefined as string | undefined,
58
+ }
59
+
60
+ if (opts.security) {
61
+ await setAuthParams(opts)
62
+ }
63
+
64
+ if (opts.requestValidator) {
65
+ await opts.requestValidator(opts)
66
+ }
67
+
68
+ if (opts.body !== undefined && opts.bodySerializer) {
69
+ opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined
70
+ }
71
+
72
+ // remove Content-Type header if body is empty to avoid sending invalid requests
73
+ if (opts.body === undefined || opts.serializedBody === '') {
74
+ opts.headers.delete('Content-Type')
75
+ }
76
+
77
+ const resolvedOpts = opts as typeof opts &
78
+ ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>
79
+ const url = buildUrl(resolvedOpts)
80
+
81
+ return { opts: resolvedOpts, url }
82
+ }
83
+
84
+ const request: Client['request'] = async (options) => {
85
+ const throwOnError = options.throwOnError ?? _config.throwOnError
86
+ const responseStyle = options.responseStyle ?? _config.responseStyle
87
+
88
+ let request: Request | undefined
89
+ let response: Response | undefined
90
+
91
+ try {
92
+ const { opts, url } = await beforeRequest(options)
93
+ const requestInit: ReqInit = {
94
+ redirect: 'follow',
95
+ ...opts,
96
+ body: getValidRequestBody(opts),
97
+ }
98
+
99
+ request = new Request(url, requestInit)
100
+
101
+ for (const fn of interceptors.request.fns) {
102
+ if (fn) {
103
+ request = await fn(request, opts)
104
+ }
105
+ }
106
+
107
+ // fetch must be assigned here, otherwise it would throw the error:
108
+ // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
109
+ const _fetch = opts.fetch!
110
+
111
+ response = await _fetch(request)
112
+
113
+ for (const fn of interceptors.response.fns) {
114
+ if (fn) {
115
+ response = await fn(response, request, opts)
116
+ }
117
+ }
118
+
119
+ const result = {
120
+ request,
121
+ response,
122
+ }
123
+
124
+ if (response.ok) {
125
+ const parseAs =
126
+ (opts.parseAs === 'auto'
127
+ ? getParseAs(response.headers.get('Content-Type'))
128
+ : opts.parseAs) ?? 'json'
129
+
130
+ if (
131
+ response.status === 204 ||
132
+ response.headers.get('Content-Length') === '0'
133
+ ) {
134
+ let emptyData: any
135
+ switch (parseAs) {
136
+ case 'arrayBuffer':
137
+ case 'blob':
138
+ case 'text':
139
+ emptyData = await response[parseAs]()
140
+ break
141
+ case 'formData':
142
+ emptyData = new FormData()
143
+ break
144
+ case 'stream':
145
+ emptyData = response.body
146
+ break
147
+ case 'json':
148
+ default:
149
+ emptyData = {}
150
+ break
151
+ }
152
+ return opts.responseStyle === 'data'
153
+ ? emptyData
154
+ : {
155
+ data: emptyData,
156
+ ...result,
157
+ }
158
+ }
159
+
160
+ let data: any
161
+ switch (parseAs) {
162
+ case 'arrayBuffer':
163
+ case 'blob':
164
+ case 'formData':
165
+ case 'text':
166
+ data = await response[parseAs]()
167
+ break
168
+ case 'json': {
169
+ // Some servers return 200 with no Content-Length and empty body.
170
+ // response.json() would throw; read as text and parse if non-empty.
171
+ const text = await response.text()
172
+ data = text ? JSON.parse(text) : {}
173
+ break
174
+ }
175
+ case 'stream':
176
+ return opts.responseStyle === 'data'
177
+ ? response.body
178
+ : {
179
+ data: response.body,
180
+ ...result,
181
+ }
182
+ }
183
+
184
+ if (parseAs === 'json') {
185
+ if (opts.responseValidator) {
186
+ await opts.responseValidator(data)
187
+ }
188
+
189
+ if (opts.responseTransformer) {
190
+ data = await opts.responseTransformer(data)
191
+ }
192
+ }
193
+
194
+ return opts.responseStyle === 'data'
195
+ ? data
196
+ : {
197
+ data,
198
+ ...result,
199
+ }
200
+ }
201
+
202
+ const textError = await response.text()
203
+ let jsonError: unknown
204
+
205
+ try {
206
+ jsonError = JSON.parse(textError)
207
+ } catch {
208
+ // noop
209
+ }
210
+
211
+ throw jsonError ?? textError
212
+ } catch (error) {
213
+ let finalError = error
214
+
215
+ for (const fn of interceptors.error.fns) {
216
+ if (fn) {
217
+ finalError = await fn(
218
+ finalError,
219
+ response,
220
+ request,
221
+ options as ResolvedRequestOptions,
222
+ )
223
+ }
224
+ }
225
+
226
+ finalError = finalError || {}
227
+
228
+ if (throwOnError) {
229
+ throw finalError
230
+ }
231
+
232
+ // TODO: we probably want to return error and improve types
233
+ return responseStyle === 'data'
234
+ ? undefined
235
+ : {
236
+ error: finalError,
237
+ request,
238
+ response,
239
+ }
240
+ }
241
+ }
242
+
243
+ const makeMethodFn =
244
+ (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
245
+ request({ ...options, method })
246
+
247
+ const makeSseFn =
248
+ (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
249
+ const { opts, url } = await beforeRequest(options)
250
+ return createSseClient({
251
+ ...opts,
252
+ body: opts.body as BodyInit | null | undefined,
253
+ method,
254
+ onRequest: async (url, init) => {
255
+ let request = new Request(url, init)
256
+ for (const fn of interceptors.request.fns) {
257
+ if (fn) {
258
+ request = await fn(request, opts)
259
+ }
260
+ }
261
+ return request
262
+ },
263
+ serializedBody: getValidRequestBody(opts) as
264
+ | BodyInit
265
+ | null
266
+ | undefined,
267
+ url,
268
+ })
269
+ }
270
+
271
+ const _buildUrl: Client['buildUrl'] = (options) =>
272
+ buildUrl({ ..._config, ...options })
273
+
274
+ return {
275
+ buildUrl: _buildUrl,
276
+ connect: makeMethodFn('CONNECT'),
277
+ delete: makeMethodFn('DELETE'),
278
+ get: makeMethodFn('GET'),
279
+ getConfig,
280
+ head: makeMethodFn('HEAD'),
281
+ interceptors,
282
+ options: makeMethodFn('OPTIONS'),
283
+ patch: makeMethodFn('PATCH'),
284
+ post: makeMethodFn('POST'),
285
+ put: makeMethodFn('PUT'),
286
+ request,
287
+ setConfig,
288
+ sse: {
289
+ connect: makeSseFn('CONNECT'),
290
+ delete: makeSseFn('DELETE'),
291
+ get: makeSseFn('GET'),
292
+ head: makeSseFn('HEAD'),
293
+ options: makeSseFn('OPTIONS'),
294
+ patch: makeSseFn('PATCH'),
295
+ post: makeSseFn('POST'),
296
+ put: makeSseFn('PUT'),
297
+ trace: makeSseFn('TRACE'),
298
+ },
299
+ trace: makeMethodFn('TRACE'),
300
+ } as Client
301
+ }
@@ -0,0 +1,27 @@
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 type { ServerSentEventsResult } from '../core/serverSentEvents.gen'
13
+ export type { ClientMeta } from '../core/types.gen'
14
+ export { createClient } from './client.gen'
15
+ export type {
16
+ Client,
17
+ ClientOptions,
18
+ Config,
19
+ CreateClientConfig,
20
+ Options,
21
+ RequestOptions,
22
+ RequestResult,
23
+ ResolvedRequestOptions,
24
+ ResponseStyle,
25
+ TDataShape,
26
+ } from './types.gen'
27
+ export { createConfig, mergeHeaders } from './utils.gen'
@@ -0,0 +1,247 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ import type { Auth } from '../core/auth.gen'
4
+ import type {
5
+ ServerSentEventsOptions,
6
+ ServerSentEventsResult,
7
+ } from '../core/serverSentEvents.gen'
8
+ import type {
9
+ Client as CoreClient,
10
+ Config as CoreConfig,
11
+ } from '../core/types.gen'
12
+ import type { Middleware } from './utils.gen'
13
+
14
+ export type ResponseStyle = 'data' | 'fields'
15
+
16
+ export interface Config<T extends ClientOptions = ClientOptions>
17
+ extends Omit<RequestInit, 'body' | 'headers' | 'method'>, CoreConfig {
18
+ /**
19
+ * Base URL for all requests made by this client.
20
+ */
21
+ baseUrl?: T['baseUrl']
22
+ /**
23
+ * Fetch API implementation. You can use this option to provide a custom
24
+ * fetch instance.
25
+ *
26
+ * @default globalThis.fetch
27
+ */
28
+ fetch?: typeof fetch
29
+ /**
30
+ * Please don't use the Fetch client for Next.js applications. The `next`
31
+ * options won't have any effect.
32
+ *
33
+ * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
34
+ */
35
+ next?: never
36
+ /**
37
+ * Return the response data parsed in a specified format. By default, `auto`
38
+ * will infer the appropriate method from the `Content-Type` response header.
39
+ * You can override this behavior with any of the {@link Body} methods.
40
+ * Select `stream` if you don't want to parse response data at all.
41
+ *
42
+ * @default 'auto'
43
+ */
44
+ parseAs?:
45
+ | 'arrayBuffer'
46
+ | 'auto'
47
+ | 'blob'
48
+ | 'formData'
49
+ | 'json'
50
+ | 'stream'
51
+ | 'text'
52
+ /**
53
+ * Should we return only data or multiple fields (data, error, response, etc.)?
54
+ *
55
+ * @default 'fields'
56
+ */
57
+ responseStyle?: ResponseStyle
58
+ /**
59
+ * Throw an error instead of returning it in the response?
60
+ *
61
+ * @default false
62
+ */
63
+ throwOnError?: T['throwOnError']
64
+ }
65
+
66
+ export interface RequestOptions<
67
+ TData = unknown,
68
+ TResponseStyle extends ResponseStyle = 'fields',
69
+ ThrowOnError extends boolean = boolean,
70
+ Url extends string = string,
71
+ >
72
+ extends
73
+ Config<{
74
+ responseStyle: TResponseStyle
75
+ throwOnError: ThrowOnError
76
+ }>,
77
+ Pick<
78
+ ServerSentEventsOptions<TData>,
79
+ | 'onRequest'
80
+ | 'onSseError'
81
+ | 'onSseEvent'
82
+ | 'sseDefaultRetryDelay'
83
+ | 'sseMaxRetryAttempts'
84
+ | 'sseMaxRetryDelay'
85
+ > {
86
+ /**
87
+ * Any body that you want to add to your request.
88
+ *
89
+ * {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
90
+ */
91
+ body?: unknown
92
+ path?: Record<string, unknown>
93
+ query?: Record<string, unknown>
94
+ /**
95
+ * Security mechanism(s) to use for the request.
96
+ */
97
+ security?: ReadonlyArray<Auth>
98
+ url: Url
99
+ }
100
+
101
+ export interface ResolvedRequestOptions<
102
+ TResponseStyle extends ResponseStyle = 'fields',
103
+ ThrowOnError extends boolean = boolean,
104
+ Url extends string = string,
105
+ > extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url> {
106
+ headers: Headers
107
+ serializedBody?: string
108
+ }
109
+
110
+ export type RequestResult<
111
+ TData = unknown,
112
+ TError = unknown,
113
+ ThrowOnError extends boolean = boolean,
114
+ TResponseStyle extends ResponseStyle = 'fields',
115
+ > = ThrowOnError extends true
116
+ ? Promise<
117
+ TResponseStyle extends 'data'
118
+ ? TData extends Record<string, unknown>
119
+ ? TData[keyof TData]
120
+ : TData
121
+ : {
122
+ data: TData extends Record<string, unknown>
123
+ ? TData[keyof TData]
124
+ : TData
125
+ request: Request
126
+ response: Response
127
+ }
128
+ >
129
+ : Promise<
130
+ TResponseStyle extends 'data'
131
+ ?
132
+ | (TData extends Record<string, unknown>
133
+ ? TData[keyof TData]
134
+ : TData)
135
+ | undefined
136
+ : (
137
+ | {
138
+ data: TData extends Record<string, unknown>
139
+ ? TData[keyof TData]
140
+ : TData
141
+ error: undefined
142
+ }
143
+ | {
144
+ data: undefined
145
+ error: TError extends Record<string, unknown>
146
+ ? TError[keyof TError]
147
+ : TError
148
+ }
149
+ ) & {
150
+ /** request may be undefined, because error may be from building the request object itself */
151
+ request?: Request
152
+ /** response may be undefined, because error may be from building the request object itself or from a network error */
153
+ response?: Response
154
+ }
155
+ >
156
+
157
+ export interface ClientOptions {
158
+ baseUrl?: string
159
+ responseStyle?: ResponseStyle
160
+ throwOnError?: boolean
161
+ }
162
+
163
+ type MethodFn = <
164
+ TData = unknown,
165
+ TError = unknown,
166
+ ThrowOnError extends boolean = false,
167
+ TResponseStyle extends ResponseStyle = 'fields',
168
+ >(
169
+ options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
170
+ ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>
171
+
172
+ type SseFn = <
173
+ TData = unknown,
174
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
175
+ _TError = unknown,
176
+ ThrowOnError extends boolean = false,
177
+ TResponseStyle extends ResponseStyle = 'fields',
178
+ >(
179
+ options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>,
180
+ ) => Promise<ServerSentEventsResult<TData>>
181
+
182
+ type RequestFn = <
183
+ TData = unknown,
184
+ TError = unknown,
185
+ ThrowOnError extends boolean = false,
186
+ TResponseStyle extends ResponseStyle = 'fields',
187
+ >(
188
+ options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> &
189
+ Pick<
190
+ Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>,
191
+ 'method'
192
+ >,
193
+ ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>
194
+
195
+ type BuildUrlFn = <
196
+ TData extends {
197
+ body?: unknown
198
+ path?: Record<string, unknown>
199
+ query?: Record<string, unknown>
200
+ url: string
201
+ },
202
+ >(
203
+ options: TData & Options<TData>,
204
+ ) => string
205
+
206
+ export type Client = CoreClient<
207
+ RequestFn,
208
+ Config,
209
+ MethodFn,
210
+ BuildUrlFn,
211
+ SseFn
212
+ > & {
213
+ interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>
214
+ }
215
+
216
+ /**
217
+ * The `createClientConfig()` function will be called on client initialization
218
+ * and the returned object will become the client's initial configuration.
219
+ *
220
+ * You may want to initialize your client this way instead of calling
221
+ * `setConfig()`. This is useful for example if you're using Next.js
222
+ * to ensure your client always has the correct values.
223
+ */
224
+ export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
225
+ override?: Config<ClientOptions & T>,
226
+ ) => Config<Required<ClientOptions> & T>
227
+
228
+ export interface TDataShape {
229
+ body?: unknown
230
+ headers?: unknown
231
+ path?: unknown
232
+ query?: unknown
233
+ url: string
234
+ }
235
+
236
+ type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>
237
+
238
+ export type Options<
239
+ TData extends TDataShape = TDataShape,
240
+ ThrowOnError extends boolean = boolean,
241
+ TResponse = unknown,
242
+ TResponseStyle extends ResponseStyle = 'fields',
243
+ > = OmitKeys<
244
+ RequestOptions<TResponse, TResponseStyle, ThrowOnError>,
245
+ 'body' | 'path' | 'query' | 'url'
246
+ > &
247
+ ([TData] extends [never] ? unknown : Omit<TData, 'url'>)