@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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @xata.io/client
2
2
 
3
+ ## 0.21.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#757](https://github.com/xataio/client-ts/pull/757) [`7da604d2`](https://github.com/xataio/client-ts/commit/7da604d27990e20ecadba6122434fca563e6a8c9) Thanks [@SferaDev](https://github.com/SferaDev)! - Add promise pool for retries
8
+
9
+ ### Patch Changes
10
+
11
+ - [#764](https://github.com/xataio/client-ts/pull/764) [`b131040a`](https://github.com/xataio/client-ts/commit/b131040a2d142c4e71a2e586fbf05cd9295af9a1) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix bun
12
+
13
+ - [#759](https://github.com/xataio/client-ts/pull/759) [`7ea810dc`](https://github.com/xataio/client-ts/commit/7ea810dc083ec284447e3bd27bd0465f887481e6) Thanks [@SferaDev](https://github.com/SferaDev)! - Expose new transaction API
14
+
15
+ - [#767](https://github.com/xataio/client-ts/pull/767) [`d124cbfb`](https://github.com/xataio/client-ts/commit/d124cbfb93d3d591e79bbe9e94c4b6304d825e71) Thanks [@SferaDev](https://github.com/SferaDev)! - Remove formatVersion from schema
16
+
17
+ - [#767](https://github.com/xataio/client-ts/pull/767) [`d124cbfb`](https://github.com/xataio/client-ts/commit/d124cbfb93d3d591e79bbe9e94c4b6304d825e71) Thanks [@SferaDev](https://github.com/SferaDev)! - Fix null value returning on date columns
18
+
19
+ - [#775](https://github.com/xataio/client-ts/pull/775) [`fb5ccdf9`](https://github.com/xataio/client-ts/commit/fb5ccdf9fa95c37d54fbc5d9c0bb45872c831609) Thanks [@SferaDev](https://github.com/SferaDev)! - Add missing target field to search
20
+
21
+ - [#760](https://github.com/xataio/client-ts/pull/760) [`4ae00036`](https://github.com/xataio/client-ts/commit/4ae00036b53c6c89e02a1fcfdd992f1a3c22892c) Thanks [@SferaDev](https://github.com/SferaDev)! - Add support for filters in boosters
22
+
23
+ - [#766](https://github.com/xataio/client-ts/pull/766) [`bdae6668`](https://github.com/xataio/client-ts/commit/bdae6668fb571d29f1b1068a54f6866a80d9b174) Thanks [@SferaDev](https://github.com/SferaDev)! - Remove beta for Workers
24
+
25
+ - [#771](https://github.com/xataio/client-ts/pull/771) [`9486bdcc`](https://github.com/xataio/client-ts/commit/9486bdccc0af567bc5f2e8f91592b0143c539c45) Thanks [@SferaDev](https://github.com/SferaDev)! - Add modifier for numeric booster
26
+
27
+ - [#771](https://github.com/xataio/client-ts/pull/771) [`9486bdcc`](https://github.com/xataio/client-ts/commit/9486bdccc0af567bc5f2e8f91592b0143c539c45) Thanks [@SferaDev](https://github.com/SferaDev)! - Add pagination to search
28
+
3
29
  ## 0.20.2
4
30
 
5
31
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const defaultTrace = async (_name, fn, _options) => {
3
+ const defaultTrace = async (name, fn, _options) => {
4
4
  return await fn({
5
+ name,
5
6
  setAttributes: () => {
6
7
  return;
7
8
  }
@@ -43,6 +44,18 @@ function isStringArray(value) {
43
44
  function isNumber(value) {
44
45
  return isDefined(value) && typeof value === "number";
45
46
  }
47
+ function parseNumber(value) {
48
+ if (isNumber(value)) {
49
+ return value;
50
+ }
51
+ if (isString(value)) {
52
+ const parsed = Number(value);
53
+ if (!Number.isNaN(parsed)) {
54
+ return parsed;
55
+ }
56
+ }
57
+ return void 0;
58
+ }
46
59
  function toBase64(value) {
47
60
  try {
48
61
  return btoa(value);
@@ -69,10 +82,13 @@ function chunk(array, chunkSize) {
69
82
  }
70
83
  return result;
71
84
  }
85
+ async function timeout(ms) {
86
+ return new Promise((resolve) => setTimeout(resolve, ms));
87
+ }
72
88
 
73
89
  function getEnvironment() {
74
90
  try {
75
- if (isObject(process) && isObject(process.env)) {
91
+ if (isDefined(process) && isDefined(process.env)) {
76
92
  return {
77
93
  apiKey: process.env.XATA_API_KEY ?? getGlobalApiKey(),
78
94
  databaseURL: process.env.XATA_DATABASE_URL ?? getGlobalDatabaseURL(),
@@ -181,6 +197,29 @@ function getAPIKey() {
181
197
  }
182
198
  }
183
199
 
200
+ var __accessCheck$8 = (obj, member, msg) => {
201
+ if (!member.has(obj))
202
+ throw TypeError("Cannot " + msg);
203
+ };
204
+ var __privateGet$8 = (obj, member, getter) => {
205
+ __accessCheck$8(obj, member, "read from private field");
206
+ return getter ? getter.call(obj) : member.get(obj);
207
+ };
208
+ var __privateAdd$8 = (obj, member, value) => {
209
+ if (member.has(obj))
210
+ throw TypeError("Cannot add the same private member more than once");
211
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
212
+ };
213
+ var __privateSet$8 = (obj, member, value, setter) => {
214
+ __accessCheck$8(obj, member, "write to private field");
215
+ setter ? setter.call(obj, value) : member.set(obj, value);
216
+ return value;
217
+ };
218
+ var __privateMethod$4 = (obj, member, method) => {
219
+ __accessCheck$8(obj, member, "access private method");
220
+ return method;
221
+ };
222
+ var _fetch, _queue, _concurrency, _enqueue, enqueue_fn;
184
223
  function getFetchImplementation(userFetch) {
185
224
  const globalFetch = typeof fetch !== "undefined" ? fetch : void 0;
186
225
  const fetchImpl = userFetch ?? globalFetch;
@@ -191,8 +230,74 @@ function getFetchImplementation(userFetch) {
191
230
  }
192
231
  return fetchImpl;
193
232
  }
233
+ class ApiRequestPool {
234
+ constructor(concurrency = 10) {
235
+ __privateAdd$8(this, _enqueue);
236
+ __privateAdd$8(this, _fetch, void 0);
237
+ __privateAdd$8(this, _queue, void 0);
238
+ __privateAdd$8(this, _concurrency, void 0);
239
+ __privateSet$8(this, _queue, []);
240
+ __privateSet$8(this, _concurrency, concurrency);
241
+ this.running = 0;
242
+ this.started = 0;
243
+ }
244
+ setFetch(fetch2) {
245
+ __privateSet$8(this, _fetch, fetch2);
246
+ }
247
+ getFetch() {
248
+ if (!__privateGet$8(this, _fetch)) {
249
+ throw new Error("Fetch not set");
250
+ }
251
+ return __privateGet$8(this, _fetch);
252
+ }
253
+ request(url, options) {
254
+ const start = new Date();
255
+ const fetch2 = this.getFetch();
256
+ const runRequest = async (stalled = false) => {
257
+ const response = await fetch2(url, options);
258
+ if (response.status === 429) {
259
+ const rateLimitReset = parseNumber(response.headers?.get("x-ratelimit-reset")) ?? 1;
260
+ await timeout(rateLimitReset * 1e3);
261
+ return await runRequest(true);
262
+ }
263
+ if (stalled) {
264
+ const stalledTime = new Date().getTime() - start.getTime();
265
+ console.warn(`A request to Xata hit your workspace limits, was retried and stalled for ${stalledTime}ms`);
266
+ }
267
+ return response;
268
+ };
269
+ return __privateMethod$4(this, _enqueue, enqueue_fn).call(this, async () => {
270
+ return await runRequest();
271
+ });
272
+ }
273
+ }
274
+ _fetch = new WeakMap();
275
+ _queue = new WeakMap();
276
+ _concurrency = new WeakMap();
277
+ _enqueue = new WeakSet();
278
+ enqueue_fn = function(task) {
279
+ const promise = new Promise((resolve) => __privateGet$8(this, _queue).push(resolve)).finally(() => {
280
+ this.started--;
281
+ this.running++;
282
+ }).then(() => task()).finally(() => {
283
+ this.running--;
284
+ const next = __privateGet$8(this, _queue).shift();
285
+ if (next !== void 0) {
286
+ this.started++;
287
+ next();
288
+ }
289
+ });
290
+ if (this.running + this.started < __privateGet$8(this, _concurrency)) {
291
+ const next = __privateGet$8(this, _queue).shift();
292
+ if (next !== void 0) {
293
+ this.started++;
294
+ next();
295
+ }
296
+ }
297
+ return promise;
298
+ };
194
299
 
195
- const VERSION = "0.20.2";
300
+ const VERSION = "0.21.0";
196
301
 
197
302
  class ErrorWithCause extends Error {
198
303
  constructor(message, options) {
@@ -235,6 +340,7 @@ function getMessage(data) {
235
340
  }
236
341
  }
237
342
 
343
+ const pool = new ApiRequestPool();
238
344
  const resolveUrl = (url, queryParams = {}, pathParams = {}) => {
239
345
  const cleanQueryParams = Object.entries(queryParams).reduce((acc, [key, value]) => {
240
346
  if (value === void 0 || value === null)
@@ -283,11 +389,13 @@ async function fetch$1({
283
389
  signal,
284
390
  clientID,
285
391
  sessionID,
392
+ clientName,
286
393
  fetchOptions = {}
287
394
  }) {
288
- return trace(
395
+ pool.setFetch(fetchImpl);
396
+ return await trace(
289
397
  `${method.toUpperCase()} ${path}`,
290
- async ({ setAttributes }) => {
398
+ async ({ name, setAttributes }) => {
291
399
  const baseUrl = buildBaseUrl({ endpoint, path, workspacesApiUrl, pathParams, apiUrl });
292
400
  const fullUrl = resolveUrl(baseUrl, queryParams, pathParams);
293
401
  const url = fullUrl.includes("localhost") ? fullUrl.replace(/^[^.]+\./, "http://") : fullUrl;
@@ -295,24 +403,26 @@ async function fetch$1({
295
403
  [TraceAttributes.HTTP_URL]: url,
296
404
  [TraceAttributes.HTTP_TARGET]: resolveUrl(path, queryParams, pathParams)
297
405
  });
298
- const response = await fetchImpl(url, {
406
+ const xataAgent = compact([
407
+ ["client", "TS_SDK"],
408
+ ["version", VERSION],
409
+ isDefined(clientName) ? ["service", clientName] : void 0
410
+ ]).map(([key, value]) => `${key}=${value}`).join("; ");
411
+ const response = await pool.request(url, {
299
412
  ...fetchOptions,
300
413
  method: method.toUpperCase(),
301
414
  body: body ? JSON.stringify(body) : void 0,
302
415
  headers: {
303
416
  "Content-Type": "application/json",
304
- "User-Agent": `Xata client-ts/${VERSION}`,
305
417
  "X-Xata-Client-ID": clientID ?? "",
306
418
  "X-Xata-Session-ID": sessionID ?? "",
419
+ "X-Xata-Agent": xataAgent,
307
420
  ...headers,
308
421
  ...hostHeader(fullUrl),
309
422
  Authorization: `Bearer ${apiKey}`
310
423
  },
311
424
  signal
312
425
  });
313
- if (response.status === 204) {
314
- return {};
315
- }
316
426
  const { host, protocol } = parseUrl(response.url);
317
427
  const requestId = response.headers?.get("x-request-id") ?? void 0;
318
428
  setAttributes({
@@ -322,6 +432,12 @@ async function fetch$1({
322
432
  [TraceAttributes.HTTP_HOST]: host,
323
433
  [TraceAttributes.HTTP_SCHEME]: protocol?.replace(":", "")
324
434
  });
435
+ if (response.status === 204) {
436
+ return {};
437
+ }
438
+ if (response.status === 429) {
439
+ throw new FetcherError(response.status, "Rate limit exceeded", requestId);
440
+ }
325
441
  try {
326
442
  const jsonResponse = await response.json();
327
443
  if (response.ok) {
@@ -773,7 +889,8 @@ class XataApiClient {
773
889
  workspacesApiUrl: getHostUrl(provider, "workspaces"),
774
890
  fetchImpl: getFetchImplementation(options.fetch),
775
891
  apiKey,
776
- trace
892
+ trace,
893
+ clientName: options.clientName
777
894
  });
778
895
  }
779
896
  get user() {
@@ -2442,7 +2559,9 @@ class RestRepository extends Query {
2442
2559
  prefix: options.prefix,
2443
2560
  highlight: options.highlight,
2444
2561
  filter: options.filter,
2445
- boosters: options.boosters
2562
+ boosters: options.boosters,
2563
+ page: options.page,
2564
+ target: options.target
2446
2565
  },
2447
2566
  ...fetchProps
2448
2567
  });
@@ -2760,10 +2879,10 @@ const initObject = (db, schemaTables, table, object, selectedColumns) => {
2760
2879
  const value = result[column.name];
2761
2880
  switch (column.type) {
2762
2881
  case "datetime": {
2763
- const date = value !== void 0 ? new Date(value) : void 0;
2764
- if (date && isNaN(date.getTime())) {
2882
+ const date = value !== void 0 ? new Date(value) : null;
2883
+ if (date !== null && isNaN(date.getTime())) {
2765
2884
  console.error(`Failed to parse date ${value} for field ${column.name}`);
2766
- } else if (date) {
2885
+ } else {
2767
2886
  result[column.name] = date;
2768
2887
  }
2769
2888
  break;
@@ -3031,10 +3150,10 @@ _schemaTables = new WeakMap();
3031
3150
  _search = new WeakSet();
3032
3151
  search_fn = async function(query, options, getFetchProps) {
3033
3152
  const fetchProps = await getFetchProps();
3034
- const { tables, fuzziness, highlight, prefix } = options ?? {};
3153
+ const { tables, fuzziness, highlight, prefix, page } = options ?? {};
3035
3154
  const { records } = await searchBranch({
3036
3155
  pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
3037
- body: { tables, query, fuzziness, prefix, highlight },
3156
+ body: { tables, query, fuzziness, prefix, highlight, page },
3038
3157
  ...fetchProps
3039
3158
  });
3040
3159
  return records;
@@ -3052,6 +3171,22 @@ getSchemaTables_fn = async function(getFetchProps) {
3052
3171
  return schema.tables;
3053
3172
  };
3054
3173
 
3174
+ class TransactionPlugin extends XataPlugin {
3175
+ build({ getFetchProps }) {
3176
+ return {
3177
+ run: async (operations) => {
3178
+ const fetchProps = await getFetchProps();
3179
+ const response = await branchTransaction({
3180
+ pathParams: { workspace: "{workspaceId}", dbBranchName: "{dbBranch}", region: "{region}" },
3181
+ body: { operations },
3182
+ ...fetchProps
3183
+ });
3184
+ return response;
3185
+ }
3186
+ };
3187
+ }
3188
+ }
3189
+
3055
3190
  const isBranchStrategyBuilder = (strategy) => {
3056
3191
  return typeof strategy === "function";
3057
3192
  };
@@ -3179,8 +3314,10 @@ const buildClient = (plugins) => {
3179
3314
  };
3180
3315
  const db = new SchemaPlugin(schemaTables).build(pluginOptions);
3181
3316
  const search = new SearchPlugin(db, schemaTables).build(pluginOptions);
3317
+ const transactions = new TransactionPlugin().build(pluginOptions);
3182
3318
  this.db = db;
3183
3319
  this.search = search;
3320
+ this.transactions = transactions;
3184
3321
  for (const [key, namespace] of Object.entries(plugins ?? {})) {
3185
3322
  if (namespace === void 0)
3186
3323
  continue;
@@ -3212,6 +3349,7 @@ const buildClient = (plugins) => {
3212
3349
  const apiKey = options?.apiKey || getAPIKey();
3213
3350
  const cache = options?.cache ?? new SimpleCache({ defaultQueryTTL: 0 });
3214
3351
  const trace = options?.trace ?? defaultTrace;
3352
+ const clientName = options?.clientName;
3215
3353
  const branch = async () => options?.branch !== void 0 ? await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, options.branch) : await getCurrentBranchName({ apiKey, databaseURL, fetchImpl: options?.fetch });
3216
3354
  if (!apiKey) {
3217
3355
  throw new Error("Option apiKey is required");
@@ -3219,8 +3357,16 @@ const buildClient = (plugins) => {
3219
3357
  if (!databaseURL) {
3220
3358
  throw new Error("Option databaseURL is required");
3221
3359
  }
3222
- return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser };
3223
- }, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({ fetch, apiKey, databaseURL, branch, trace, clientID }) {
3360
+ return { fetch, databaseURL, apiKey, branch, cache, trace, clientID: generateUUID(), enableBrowser, clientName };
3361
+ }, _getFetchProps = new WeakSet(), getFetchProps_fn = async function({
3362
+ fetch,
3363
+ apiKey,
3364
+ databaseURL,
3365
+ branch,
3366
+ trace,
3367
+ clientID,
3368
+ clientName
3369
+ }) {
3224
3370
  const branchValue = await __privateMethod(this, _evaluateBranch, evaluateBranch_fn).call(this, branch);
3225
3371
  if (!branchValue)
3226
3372
  throw new Error("Unable to resolve branch value");
@@ -3234,7 +3380,8 @@ const buildClient = (plugins) => {
3234
3380
  return databaseURL + newPath;
3235
3381
  },
3236
3382
  trace,
3237
- clientID
3383
+ clientID,
3384
+ clientName
3238
3385
  };
3239
3386
  }, _evaluateBranch = new WeakSet(), evaluateBranch_fn = async function(param) {
3240
3387
  if (__privateGet(this, _branch))