@xata.io/client 0.20.2 → 0.21.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.
package/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
- const defaultTrace = async (_name, fn, _options) => {
1
+ const defaultTrace = async (name, fn, _options) => {
2
2
  return await fn({
3
+ name,
3
4
  setAttributes: () => {
4
5
  return;
5
6
  }
@@ -41,6 +42,18 @@ function isStringArray(value) {
41
42
  function isNumber(value) {
42
43
  return isDefined(value) && typeof value === "number";
43
44
  }
45
+ function parseNumber(value) {
46
+ if (isNumber(value)) {
47
+ return value;
48
+ }
49
+ if (isString(value)) {
50
+ const parsed = Number(value);
51
+ if (!Number.isNaN(parsed)) {
52
+ return parsed;
53
+ }
54
+ }
55
+ return void 0;
56
+ }
44
57
  function toBase64(value) {
45
58
  try {
46
59
  return btoa(value);
@@ -67,10 +80,13 @@ function chunk(array, chunkSize) {
67
80
  }
68
81
  return result;
69
82
  }
83
+ async function timeout(ms) {
84
+ return new Promise((resolve) => setTimeout(resolve, ms));
85
+ }
70
86
 
71
87
  function getEnvironment() {
72
88
  try {
73
- if (isObject(process) && isObject(process.env)) {
89
+ if (isDefined(process) && isDefined(process.env)) {
74
90
  return {
75
91
  apiKey: process.env.XATA_API_KEY ?? getGlobalApiKey(),
76
92
  databaseURL: process.env.XATA_DATABASE_URL ?? getGlobalDatabaseURL(),
@@ -179,6 +195,29 @@ function getAPIKey() {
179
195
  }
180
196
  }
181
197
 
198
+ var __accessCheck$8 = (obj, member, msg) => {
199
+ if (!member.has(obj))
200
+ throw TypeError("Cannot " + msg);
201
+ };
202
+ var __privateGet$8 = (obj, member, getter) => {
203
+ __accessCheck$8(obj, member, "read from private field");
204
+ return getter ? getter.call(obj) : member.get(obj);
205
+ };
206
+ var __privateAdd$8 = (obj, member, value) => {
207
+ if (member.has(obj))
208
+ throw TypeError("Cannot add the same private member more than once");
209
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
210
+ };
211
+ var __privateSet$8 = (obj, member, value, setter) => {
212
+ __accessCheck$8(obj, member, "write to private field");
213
+ setter ? setter.call(obj, value) : member.set(obj, value);
214
+ return value;
215
+ };
216
+ var __privateMethod$4 = (obj, member, method) => {
217
+ __accessCheck$8(obj, member, "access private method");
218
+ return method;
219
+ };
220
+ var _fetch, _queue, _concurrency, _enqueue, enqueue_fn;
182
221
  function getFetchImplementation(userFetch) {
183
222
  const globalFetch = typeof fetch !== "undefined" ? fetch : void 0;
184
223
  const fetchImpl = userFetch ?? globalFetch;
@@ -189,8 +228,74 @@ function getFetchImplementation(userFetch) {
189
228
  }
190
229
  return fetchImpl;
191
230
  }
231
+ class ApiRequestPool {
232
+ constructor(concurrency = 10) {
233
+ __privateAdd$8(this, _enqueue);
234
+ __privateAdd$8(this, _fetch, void 0);
235
+ __privateAdd$8(this, _queue, void 0);
236
+ __privateAdd$8(this, _concurrency, void 0);
237
+ __privateSet$8(this, _queue, []);
238
+ __privateSet$8(this, _concurrency, concurrency);
239
+ this.running = 0;
240
+ this.started = 0;
241
+ }
242
+ setFetch(fetch2) {
243
+ __privateSet$8(this, _fetch, fetch2);
244
+ }
245
+ getFetch() {
246
+ if (!__privateGet$8(this, _fetch)) {
247
+ throw new Error("Fetch not set");
248
+ }
249
+ return __privateGet$8(this, _fetch);
250
+ }
251
+ request(url, options) {
252
+ const start = new Date();
253
+ const fetch2 = this.getFetch();
254
+ const runRequest = async (stalled = false) => {
255
+ const response = await fetch2(url, options);
256
+ if (response.status === 429) {
257
+ const rateLimitReset = parseNumber(response.headers?.get("x-ratelimit-reset")) ?? 1;
258
+ await timeout(rateLimitReset * 1e3);
259
+ return await runRequest(true);
260
+ }
261
+ if (stalled) {
262
+ const stalledTime = new Date().getTime() - start.getTime();
263
+ console.warn(`A request to Xata hit your workspace limits, was retried and stalled for ${stalledTime}ms`);
264
+ }
265
+ return response;
266
+ };
267
+ return __privateMethod$4(this, _enqueue, enqueue_fn).call(this, async () => {
268
+ return await runRequest();
269
+ });
270
+ }
271
+ }
272
+ _fetch = new WeakMap();
273
+ _queue = new WeakMap();
274
+ _concurrency = new WeakMap();
275
+ _enqueue = new WeakSet();
276
+ enqueue_fn = function(task) {
277
+ const promise = new Promise((resolve) => __privateGet$8(this, _queue).push(resolve)).finally(() => {
278
+ this.started--;
279
+ this.running++;
280
+ }).then(() => task()).finally(() => {
281
+ this.running--;
282
+ const next = __privateGet$8(this, _queue).shift();
283
+ if (next !== void 0) {
284
+ this.started++;
285
+ next();
286
+ }
287
+ });
288
+ if (this.running + this.started < __privateGet$8(this, _concurrency)) {
289
+ const next = __privateGet$8(this, _queue).shift();
290
+ if (next !== void 0) {
291
+ this.started++;
292
+ next();
293
+ }
294
+ }
295
+ return promise;
296
+ };
192
297
 
193
- const VERSION = "0.20.2";
298
+ const VERSION = "0.21.0";
194
299
 
195
300
  class ErrorWithCause extends Error {
196
301
  constructor(message, options) {
@@ -233,6 +338,7 @@ function getMessage(data) {
233
338
  }
234
339
  }
235
340
 
341
+ const pool = new ApiRequestPool();
236
342
  const resolveUrl = (url, queryParams = {}, pathParams = {}) => {
237
343
  const cleanQueryParams = Object.entries(queryParams).reduce((acc, [key, value]) => {
238
344
  if (value === void 0 || value === null)
@@ -281,11 +387,13 @@ async function fetch$1({
281
387
  signal,
282
388
  clientID,
283
389
  sessionID,
390
+ clientName,
284
391
  fetchOptions = {}
285
392
  }) {
286
- return trace(
393
+ pool.setFetch(fetchImpl);
394
+ return await trace(
287
395
  `${method.toUpperCase()} ${path}`,
288
- async ({ setAttributes }) => {
396
+ async ({ name, setAttributes }) => {
289
397
  const baseUrl = buildBaseUrl({ endpoint, path, workspacesApiUrl, pathParams, apiUrl });
290
398
  const fullUrl = resolveUrl(baseUrl, queryParams, pathParams);
291
399
  const url = fullUrl.includes("localhost") ? fullUrl.replace(/^[^.]+\./, "http://") : fullUrl;
@@ -293,24 +401,26 @@ async function fetch$1({
293
401
  [TraceAttributes.HTTP_URL]: url,
294
402
  [TraceAttributes.HTTP_TARGET]: resolveUrl(path, queryParams, pathParams)
295
403
  });
296
- const response = await fetchImpl(url, {
404
+ const xataAgent = compact([
405
+ ["client", "TS_SDK"],
406
+ ["version", VERSION],
407
+ isDefined(clientName) ? ["service", clientName] : void 0
408
+ ]).map(([key, value]) => `${key}=${value}`).join("; ");
409
+ const response = await pool.request(url, {
297
410
  ...fetchOptions,
298
411
  method: method.toUpperCase(),
299
412
  body: body ? JSON.stringify(body) : void 0,
300
413
  headers: {
301
414
  "Content-Type": "application/json",
302
- "User-Agent": `Xata client-ts/${VERSION}`,
303
415
  "X-Xata-Client-ID": clientID ?? "",
304
416
  "X-Xata-Session-ID": sessionID ?? "",
417
+ "X-Xata-Agent": xataAgent,
305
418
  ...headers,
306
419
  ...hostHeader(fullUrl),
307
420
  Authorization: `Bearer ${apiKey}`
308
421
  },
309
422
  signal
310
423
  });
311
- if (response.status === 204) {
312
- return {};
313
- }
314
424
  const { host, protocol } = parseUrl(response.url);
315
425
  const requestId = response.headers?.get("x-request-id") ?? void 0;
316
426
  setAttributes({
@@ -320,6 +430,12 @@ async function fetch$1({
320
430
  [TraceAttributes.HTTP_HOST]: host,
321
431
  [TraceAttributes.HTTP_SCHEME]: protocol?.replace(":", "")
322
432
  });
433
+ if (response.status === 204) {
434
+ return {};
435
+ }
436
+ if (response.status === 429) {
437
+ throw new FetcherError(response.status, "Rate limit exceeded", requestId);
438
+ }
323
439
  try {
324
440
  const jsonResponse = await response.json();
325
441
  if (response.ok) {
@@ -771,7 +887,8 @@ class XataApiClient {
771
887
  workspacesApiUrl: getHostUrl(provider, "workspaces"),
772
888
  fetchImpl: getFetchImplementation(options.fetch),
773
889
  apiKey,
774
- trace
890
+ trace,
891
+ clientName: options.clientName
775
892
  });
776
893
  }
777
894
  get user() {
@@ -2440,7 +2557,9 @@ class RestRepository extends Query {
2440
2557
  prefix: options.prefix,
2441
2558
  highlight: options.highlight,
2442
2559
  filter: options.filter,
2443
- boosters: options.boosters
2560
+ boosters: options.boosters,
2561
+ page: options.page,
2562
+ target: options.target
2444
2563
  },
2445
2564
  ...fetchProps
2446
2565
  });
@@ -2758,10 +2877,10 @@ const initObject = (db, schemaTables, table, object, selectedColumns) => {
2758
2877
  const value = result[column.name];
2759
2878
  switch (column.type) {
2760
2879
  case "datetime": {
2761
- const date = value !== void 0 ? new Date(value) : void 0;
2762
- if (date && isNaN(date.getTime())) {
2880
+ const date = value !== void 0 ? new Date(value) : null;
2881
+ if (date !== null && isNaN(date.getTime())) {
2763
2882
  console.error(`Failed to parse date ${value} for field ${column.name}`);
2764
- } else if (date) {
2883
+ } else {
2765
2884
  result[column.name] = date;
2766
2885
  }
2767
2886
  break;
@@ -3029,10 +3148,10 @@ _schemaTables = new WeakMap();
3029
3148
  _search = new WeakSet();
3030
3149
  search_fn = async function(query, options, getFetchProps) {
3031
3150
  const fetchProps = await getFetchProps();
3032
- const { tables, fuzziness, highlight, prefix } = options ?? {};
3151
+ const { tables, fuzziness, highlight, prefix, page } = options ?? {};
3033
3152
  const { records } = await searchBranch({
3034
3153
  pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
3035
- body: { tables, query, fuzziness, prefix, highlight },
3154
+ body: { tables, query, fuzziness, prefix, highlight, page },
3036
3155
  ...fetchProps
3037
3156
  });
3038
3157
  return records;
@@ -3050,6 +3169,22 @@ getSchemaTables_fn = async function(getFetchProps) {
3050
3169
  return schema.tables;
3051
3170
  };
3052
3171
 
3172
+ class TransactionPlugin extends XataPlugin {
3173
+ build({ getFetchProps }) {
3174
+ return {
3175
+ run: async (operations) => {
3176
+ const fetchProps = await getFetchProps();
3177
+ const response = await branchTransaction({
3178
+ pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
3179
+ body: { operations },
3180
+ ...fetchProps
3181
+ });
3182
+ return response;
3183
+ }
3184
+ };
3185
+ }
3186
+ }
3187
+
3053
3188
  const isBranchStrategyBuilder = (strategy) => {
3054
3189
  return typeof strategy === "function";
3055
3190
  };
@@ -3177,8 +3312,10 @@ const buildClient = (plugins) => {
3177
3312
  };
3178
3313
  const db = new SchemaPlugin(schemaTables).build(pluginOptions);
3179
3314
  const search = new SearchPlugin(db, schemaTables).build(pluginOptions);
3315
+ const transactions = new TransactionPlugin().build(pluginOptions);
3180
3316
  this.db = db;
3181
3317
  this.search = search;
3318
+ this.transactions = transactions;
3182
3319
  for (const [key, namespace] of Object.entries(plugins ?? {})) {
3183
3320
  if (namespace === void 0)
3184
3321
  continue;
@@ -3210,6 +3347,7 @@ const buildClient = (plugins) => {
3210
3347
  const apiKey = options?.apiKey || getAPIKey();
3211
3348
  const cache = options?.cache ?? new SimpleCache({ defaultQueryTTL: 0 });
3212
3349
  const trace = options?.trace ?? defaultTrace;
3350
+ const clientName = options?.clientName;
3213
3351
  const branch = async () => options?.branch !== void 0 ? await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, options.branch) : await getCurrentBranchName({ apiKey, databaseURL, fetchImpl: options?.fetch });
3214
3352
  if (!apiKey) {
3215
3353
  throw new Error("Option apiKey is required");
@@ -3217,8 +3355,16 @@ const buildClient = (plugins) => {
3217
3355
  if (!databaseURL) {
3218
3356
  throw new Error("Option databaseURL is required");
3219
3357
  }
3220
- return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser };
3221
- }, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({ fetch, apiKey, databaseURL, branch, trace, clientID }) {
3358
+ return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser, clientName };
3359
+ }, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({
3360
+ fetch,
3361
+ apiKey,
3362
+ databaseURL,
3363
+ branch,
3364
+ trace,
3365
+ clientID,
3366
+ clientName
3367
+ }) {
3222
3368
  const branchValue = await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, branch);
3223
3369
  if (!branchValue)
3224
3370
  throw new Error("Unable to resolve branch value");
@@ -3232,7 +3378,8 @@ const buildClient = (plugins) => {
3232
3378
  return databaseURL + newPath;
3233
3379
  },
3234
3380
  trace,
3235
- clientID
3381
+ clientID,
3382
+ clientName
3236
3383
  };
3237
3384
  }, _evaluateBranch = new WeakSet(), evaluateBranch_fn = async function(param) {
3238
3385
  if (__privateGet(this, _branch))