@xata.io/client 0.20.2 → 0.21.1

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.1";
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,27 @@ 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: {
414
+ "Accept-Encoding": "identity",
301
415
  "Content-Type": "application/json",
302
- "User-Agent": `Xata client-ts/${VERSION}`,
303
416
  "X-Xata-Client-ID": clientID ?? "",
304
417
  "X-Xata-Session-ID": sessionID ?? "",
418
+ "X-Xata-Agent": xataAgent,
305
419
  ...headers,
306
420
  ...hostHeader(fullUrl),
307
421
  Authorization: `Bearer ${apiKey}`
308
422
  },
309
423
  signal
310
424
  });
311
- if (response.status === 204) {
312
- return {};
313
- }
314
425
  const { host, protocol } = parseUrl(response.url);
315
426
  const requestId = response.headers?.get("x-request-id") ?? void 0;
316
427
  setAttributes({
@@ -320,6 +431,12 @@ async function fetch$1({
320
431
  [TraceAttributes.HTTP_HOST]: host,
321
432
  [TraceAttributes.HTTP_SCHEME]: protocol?.replace(":", "")
322
433
  });
434
+ if (response.status === 204) {
435
+ return {};
436
+ }
437
+ if (response.status === 429) {
438
+ throw new FetcherError(response.status, "Rate limit exceeded", requestId);
439
+ }
323
440
  try {
324
441
  const jsonResponse = await response.json();
325
442
  if (response.ok) {
@@ -771,7 +888,8 @@ class XataApiClient {
771
888
  workspacesApiUrl: getHostUrl(provider, "workspaces"),
772
889
  fetchImpl: getFetchImplementation(options.fetch),
773
890
  apiKey,
774
- trace
891
+ trace,
892
+ clientName: options.clientName
775
893
  });
776
894
  }
777
895
  get user() {
@@ -2303,13 +2421,19 @@ class RestRepository extends Query {
2303
2421
  const result = await this.read(a, columns);
2304
2422
  return result;
2305
2423
  }
2306
- if (isString(a) && isObject(b)) {
2307
- const columns = isStringArray(c) ? c : void 0;
2308
- return __privateMethod$2(this, _updateRecordWithID, updateRecordWithID_fn).call(this, a, b, columns, { ifVersion });
2309
- }
2310
- if (isObject(a) && isString(a.id)) {
2311
- const columns = isStringArray(b) ? b : void 0;
2312
- return __privateMethod$2(this, _updateRecordWithID, updateRecordWithID_fn).call(this, a.id, { ...a, id: void 0 }, columns, { ifVersion });
2424
+ try {
2425
+ if (isString(a) && isObject(b)) {
2426
+ const columns = isStringArray(c) ? c : void 0;
2427
+ return await __privateMethod$2(this, _updateRecordWithID, updateRecordWithID_fn).call(this, a, b, columns, { ifVersion });
2428
+ }
2429
+ if (isObject(a) && isString(a.id)) {
2430
+ const columns = isStringArray(b) ? b : void 0;
2431
+ return await __privateMethod$2(this, _updateRecordWithID, updateRecordWithID_fn).call(this, a.id, { ...a, id: void 0 }, columns, { ifVersion });
2432
+ }
2433
+ } catch (error) {
2434
+ if (error.status === 422)
2435
+ return null;
2436
+ throw error;
2313
2437
  }
2314
2438
  throw new Error("Invalid arguments for update method");
2315
2439
  });
@@ -2440,7 +2564,9 @@ class RestRepository extends Query {
2440
2564
  prefix: options.prefix,
2441
2565
  highlight: options.highlight,
2442
2566
  filter: options.filter,
2443
- boosters: options.boosters
2567
+ boosters: options.boosters,
2568
+ page: options.page,
2569
+ target: options.target
2444
2570
  },
2445
2571
  ...fetchProps
2446
2572
  });
@@ -2758,10 +2884,10 @@ const initObject = (db, schemaTables, table, object, selectedColumns) => {
2758
2884
  const value = result[column.name];
2759
2885
  switch (column.type) {
2760
2886
  case "datetime": {
2761
- const date = value !== void 0 ? new Date(value) : void 0;
2762
- if (date && isNaN(date.getTime())) {
2887
+ const date = value !== void 0 ? new Date(value) : null;
2888
+ if (date !== null && isNaN(date.getTime())) {
2763
2889
  console.error(`Failed to parse date ${value} for field ${column.name}`);
2764
- } else if (date) {
2890
+ } else {
2765
2891
  result[column.name] = date;
2766
2892
  }
2767
2893
  break;
@@ -3029,10 +3155,10 @@ _schemaTables = new WeakMap();
3029
3155
  _search = new WeakSet();
3030
3156
  search_fn = async function(query, options, getFetchProps) {
3031
3157
  const fetchProps = await getFetchProps();
3032
- const { tables, fuzziness, highlight, prefix } = options ?? {};
3158
+ const { tables, fuzziness, highlight, prefix, page } = options ?? {};
3033
3159
  const { records } = await searchBranch({
3034
3160
  pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
3035
- body: { tables, query, fuzziness, prefix, highlight },
3161
+ body: { tables, query, fuzziness, prefix, highlight, page },
3036
3162
  ...fetchProps
3037
3163
  });
3038
3164
  return records;
@@ -3050,6 +3176,22 @@ getSchemaTables_fn = async function(getFetchProps) {
3050
3176
  return schema.tables;
3051
3177
  };
3052
3178
 
3179
+ class TransactionPlugin extends XataPlugin {
3180
+ build({ getFetchProps }) {
3181
+ return {
3182
+ run: async (operations) => {
3183
+ const fetchProps = await getFetchProps();
3184
+ const response = await branchTransaction({
3185
+ pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
3186
+ body: { operations },
3187
+ ...fetchProps
3188
+ });
3189
+ return response;
3190
+ }
3191
+ };
3192
+ }
3193
+ }
3194
+
3053
3195
  const isBranchStrategyBuilder = (strategy) => {
3054
3196
  return typeof strategy === "function";
3055
3197
  };
@@ -3177,8 +3319,10 @@ const buildClient = (plugins) => {
3177
3319
  };
3178
3320
  const db = new SchemaPlugin(schemaTables).build(pluginOptions);
3179
3321
  const search = new SearchPlugin(db, schemaTables).build(pluginOptions);
3322
+ const transactions = new TransactionPlugin().build(pluginOptions);
3180
3323
  this.db = db;
3181
3324
  this.search = search;
3325
+ this.transactions = transactions;
3182
3326
  for (const [key, namespace] of Object.entries(plugins ?? {})) {
3183
3327
  if (namespace === void 0)
3184
3328
  continue;
@@ -3210,6 +3354,7 @@ const buildClient = (plugins) => {
3210
3354
  const apiKey = options?.apiKey || getAPIKey();
3211
3355
  const cache = options?.cache ?? new SimpleCache({ defaultQueryTTL: 0 });
3212
3356
  const trace = options?.trace ?? defaultTrace;
3357
+ const clientName = options?.clientName;
3213
3358
  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
3359
  if (!apiKey) {
3215
3360
  throw new Error("Option apiKey is required");
@@ -3217,8 +3362,16 @@ const buildClient = (plugins) => {
3217
3362
  if (!databaseURL) {
3218
3363
  throw new Error("Option databaseURL is required");
3219
3364
  }
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 }) {
3365
+ return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser, clientName };
3366
+ }, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({
3367
+ fetch,
3368
+ apiKey,
3369
+ databaseURL,
3370
+ branch,
3371
+ trace,
3372
+ clientID,
3373
+ clientName
3374
+ }) {
3222
3375
  const branchValue = await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, branch);
3223
3376
  if (!branchValue)
3224
3377
  throw new Error("Unable to resolve branch value");
@@ -3232,7 +3385,8 @@ const buildClient = (plugins) => {
3232
3385
  return databaseURL + newPath;
3233
3386
  },
3234
3387
  trace,
3235
- clientID
3388
+ clientID,
3389
+ clientName
3236
3390
  };
3237
3391
  }, _evaluateBranch = new WeakSet(), evaluateBranch_fn = async function(param) {
3238
3392
  if (__privateGet(this, _branch))